1 |
From 2b382bed2918d3399c4c7f3acf192c15906157d2 Mon Sep 17 00:00:00 2001 |
2 |
From: Sasha Levin <sashal@kernel.org> |
3 |
Date: Wed, 24 Aug 2022 09:50:51 -0700 |
4 |
Subject: ionic: VF initial random MAC address if no assigned mac |
5 |
|
6 |
From: R Mohamed Shah <mohamed@pensando.io> |
7 |
|
8 |
[ Upstream commit 19058be7c48ceb3e60fa3948e24da1059bd68ee4 ] |
9 |
|
10 |
Assign a random mac address to the VF interface station |
11 |
address if it boots with a zero mac address in order to match |
12 |
similar behavior seen in other VF drivers. Handle the errors |
13 |
where the older firmware does not allow the VF to set its own |
14 |
station address. |
15 |
|
16 |
Newer firmware will allow the VF to set the station mac address |
17 |
if it hasn't already been set administratively through the PF. |
18 |
Setting it will also be allowed if the VF has trust. |
19 |
|
20 |
Fixes: fbb39807e9ae ("ionic: support sr-iov operations") |
21 |
Signed-off-by: R Mohamed Shah <mohamed@pensando.io> |
22 |
Signed-off-by: Shannon Nelson <snelson@pensando.io> |
23 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
24 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
25 |
--- |
26 |
.../net/ethernet/pensando/ionic/ionic_lif.c | 92 ++++++++++++++++++- |
27 |
1 file changed, 87 insertions(+), 5 deletions(-) |
28 |
|
29 |
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c |
30 |
index d4226999547e8..0be79c5167813 100644 |
31 |
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c |
32 |
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c |
33 |
@@ -1564,8 +1564,67 @@ static int ionic_set_features(struct net_device *netdev, |
34 |
return err; |
35 |
} |
36 |
|
37 |
+static int ionic_set_attr_mac(struct ionic_lif *lif, u8 *mac) |
38 |
+{ |
39 |
+ struct ionic_admin_ctx ctx = { |
40 |
+ .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), |
41 |
+ .cmd.lif_setattr = { |
42 |
+ .opcode = IONIC_CMD_LIF_SETATTR, |
43 |
+ .index = cpu_to_le16(lif->index), |
44 |
+ .attr = IONIC_LIF_ATTR_MAC, |
45 |
+ }, |
46 |
+ }; |
47 |
+ |
48 |
+ ether_addr_copy(ctx.cmd.lif_setattr.mac, mac); |
49 |
+ return ionic_adminq_post_wait(lif, &ctx); |
50 |
+} |
51 |
+ |
52 |
+static int ionic_get_attr_mac(struct ionic_lif *lif, u8 *mac_addr) |
53 |
+{ |
54 |
+ struct ionic_admin_ctx ctx = { |
55 |
+ .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), |
56 |
+ .cmd.lif_getattr = { |
57 |
+ .opcode = IONIC_CMD_LIF_GETATTR, |
58 |
+ .index = cpu_to_le16(lif->index), |
59 |
+ .attr = IONIC_LIF_ATTR_MAC, |
60 |
+ }, |
61 |
+ }; |
62 |
+ int err; |
63 |
+ |
64 |
+ err = ionic_adminq_post_wait(lif, &ctx); |
65 |
+ if (err) |
66 |
+ return err; |
67 |
+ |
68 |
+ ether_addr_copy(mac_addr, ctx.comp.lif_getattr.mac); |
69 |
+ return 0; |
70 |
+} |
71 |
+ |
72 |
+static int ionic_program_mac(struct ionic_lif *lif, u8 *mac) |
73 |
+{ |
74 |
+ u8 get_mac[ETH_ALEN]; |
75 |
+ int err; |
76 |
+ |
77 |
+ err = ionic_set_attr_mac(lif, mac); |
78 |
+ if (err) |
79 |
+ return err; |
80 |
+ |
81 |
+ err = ionic_get_attr_mac(lif, get_mac); |
82 |
+ if (err) |
83 |
+ return err; |
84 |
+ |
85 |
+ /* To deal with older firmware that silently ignores the set attr mac: |
86 |
+ * doesn't actually change the mac and doesn't return an error, so we |
87 |
+ * do the get attr to verify whether or not the set actually happened |
88 |
+ */ |
89 |
+ if (!ether_addr_equal(get_mac, mac)) |
90 |
+ return 1; |
91 |
+ |
92 |
+ return 0; |
93 |
+} |
94 |
+ |
95 |
static int ionic_set_mac_address(struct net_device *netdev, void *sa) |
96 |
{ |
97 |
+ struct ionic_lif *lif = netdev_priv(netdev); |
98 |
struct sockaddr *addr = sa; |
99 |
u8 *mac; |
100 |
int err; |
101 |
@@ -1574,6 +1633,14 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) |
102 |
if (ether_addr_equal(netdev->dev_addr, mac)) |
103 |
return 0; |
104 |
|
105 |
+ err = ionic_program_mac(lif, mac); |
106 |
+ if (err < 0) |
107 |
+ return err; |
108 |
+ |
109 |
+ if (err > 0) |
110 |
+ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", |
111 |
+ __func__); |
112 |
+ |
113 |
err = eth_prepare_mac_addr_change(netdev, addr); |
114 |
if (err) |
115 |
return err; |
116 |
@@ -3172,6 +3239,7 @@ static int ionic_station_set(struct ionic_lif *lif) |
117 |
.attr = IONIC_LIF_ATTR_MAC, |
118 |
}, |
119 |
}; |
120 |
+ u8 mac_address[ETH_ALEN]; |
121 |
struct sockaddr addr; |
122 |
int err; |
123 |
|
124 |
@@ -3180,8 +3248,23 @@ static int ionic_station_set(struct ionic_lif *lif) |
125 |
return err; |
126 |
netdev_dbg(lif->netdev, "found initial MAC addr %pM\n", |
127 |
ctx.comp.lif_getattr.mac); |
128 |
- if (is_zero_ether_addr(ctx.comp.lif_getattr.mac)) |
129 |
- return 0; |
130 |
+ ether_addr_copy(mac_address, ctx.comp.lif_getattr.mac); |
131 |
+ |
132 |
+ if (is_zero_ether_addr(mac_address)) { |
133 |
+ eth_hw_addr_random(netdev); |
134 |
+ netdev_dbg(netdev, "Random Mac generated: %pM\n", netdev->dev_addr); |
135 |
+ ether_addr_copy(mac_address, netdev->dev_addr); |
136 |
+ |
137 |
+ err = ionic_program_mac(lif, mac_address); |
138 |
+ if (err < 0) |
139 |
+ return err; |
140 |
+ |
141 |
+ if (err > 0) { |
142 |
+ netdev_dbg(netdev, "%s:SET/GET ATTR Mac are not same-due to old FW running\n", |
143 |
+ __func__); |
144 |
+ return 0; |
145 |
+ } |
146 |
+ } |
147 |
|
148 |
if (!is_zero_ether_addr(netdev->dev_addr)) { |
149 |
/* If the netdev mac is non-zero and doesn't match the default |
150 |
@@ -3189,12 +3272,11 @@ static int ionic_station_set(struct ionic_lif *lif) |
151 |
* likely here again after a fw-upgrade reset. We need to be |
152 |
* sure the netdev mac is in our filter list. |
153 |
*/ |
154 |
- if (!ether_addr_equal(ctx.comp.lif_getattr.mac, |
155 |
- netdev->dev_addr)) |
156 |
+ if (!ether_addr_equal(mac_address, netdev->dev_addr)) |
157 |
ionic_lif_addr_add(lif, netdev->dev_addr); |
158 |
} else { |
159 |
/* Update the netdev mac with the device's mac */ |
160 |
- memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len); |
161 |
+ ether_addr_copy(addr.sa_data, mac_address); |
162 |
addr.sa_family = AF_INET; |
163 |
err = eth_prepare_mac_addr_change(netdev, &addr); |
164 |
if (err) { |
165 |
-- |
166 |
2.35.1 |
167 |
|