]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ionic: VF initial random MAC address if no assigned mac
authorR Mohamed Shah <mohamed@pensando.io>
Wed, 24 Aug 2022 16:50:51 +0000 (09:50 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Aug 2022 19:39:54 +0000 (12:39 -0700)
Assign a random mac address to the VF interface station
address if it boots with a zero mac address in order to match
similar behavior seen in other VF drivers.  Handle the errors
where the older firmware does not allow the VF to set its own
station address.

Newer firmware will allow the VF to set the station mac address
if it hasn't already been set administratively through the PF.
Setting it will also be allowed if the VF has trust.

Fixes: a1287907419d ("ionic: support sr-iov operations")
Signed-off-by: R Mohamed Shah <mohamed@pensando.io>
Signed-off-by: Shannon Nelson <snelson@pensando.io>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/pensando/ionic/ionic_lif.c

index d4226999547e870ee4f0c42d36aa171651e0caaa..0be79c51678133c7b98668d1670cfeeb54bafb85 100644 (file)
@@ -1564,8 +1564,67 @@ static int ionic_set_features(struct net_device *netdev,
        return err;
 }
 
+static int ionic_set_attr_mac(struct ionic_lif *lif, u8 *mac)
+{
+       struct ionic_admin_ctx ctx = {
+               .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
+               .cmd.lif_setattr = {
+                       .opcode = IONIC_CMD_LIF_SETATTR,
+                       .index = cpu_to_le16(lif->index),
+                       .attr = IONIC_LIF_ATTR_MAC,
+               },
+       };
+
+       ether_addr_copy(ctx.cmd.lif_setattr.mac, mac);
+       return ionic_adminq_post_wait(lif, &ctx);
+}
+
+static int ionic_get_attr_mac(struct ionic_lif *lif, u8 *mac_addr)
+{
+       struct ionic_admin_ctx ctx = {
+               .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
+               .cmd.lif_getattr = {
+                       .opcode = IONIC_CMD_LIF_GETATTR,
+                       .index = cpu_to_le16(lif->index),
+                       .attr = IONIC_LIF_ATTR_MAC,
+               },
+       };
+       int err;
+
+       err = ionic_adminq_post_wait(lif, &ctx);
+       if (err)
+               return err;
+
+       ether_addr_copy(mac_addr, ctx.comp.lif_getattr.mac);
+       return 0;
+}
+
+static int ionic_program_mac(struct ionic_lif *lif, u8 *mac)
+{
+       u8  get_mac[ETH_ALEN];
+       int err;
+
+       err = ionic_set_attr_mac(lif, mac);
+       if (err)
+               return err;
+
+       err = ionic_get_attr_mac(lif, get_mac);
+       if (err)
+               return err;
+
+       /* To deal with older firmware that silently ignores the set attr mac:
+        * doesn't actually change the mac and doesn't return an error, so we
+        * do the get attr to verify whether or not the set actually happened
+        */
+       if (!ether_addr_equal(get_mac, mac))
+               return 1;
+
+       return 0;
+}
+
 static int ionic_set_mac_address(struct net_device *netdev, void *sa)
 {
+       struct ionic_lif *lif = netdev_priv(netdev);
        struct sockaddr *addr = sa;
        u8 *mac;
        int err;
@@ -1574,6 +1633,14 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
        if (ether_addr_equal(netdev->dev_addr, mac))
                return 0;
 
+       err = ionic_program_mac(lif, mac);
+       if (err < 0)
+               return err;
+
+       if (err > 0)
+               netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
+                          __func__);
+
        err = eth_prepare_mac_addr_change(netdev, addr);
        if (err)
                return err;
@@ -3172,6 +3239,7 @@ static int ionic_station_set(struct ionic_lif *lif)
                        .attr = IONIC_LIF_ATTR_MAC,
                },
        };
+       u8 mac_address[ETH_ALEN];
        struct sockaddr addr;
        int err;
 
@@ -3180,8 +3248,23 @@ static int ionic_station_set(struct ionic_lif *lif)
                return err;
        netdev_dbg(lif->netdev, "found initial MAC addr %pM\n",
                   ctx.comp.lif_getattr.mac);
-       if (is_zero_ether_addr(ctx.comp.lif_getattr.mac))
-               return 0;
+       ether_addr_copy(mac_address, ctx.comp.lif_getattr.mac);
+
+       if (is_zero_ether_addr(mac_address)) {
+               eth_hw_addr_random(netdev);
+               netdev_dbg(netdev, "Random Mac generated: %pM\n", netdev->dev_addr);
+               ether_addr_copy(mac_address, netdev->dev_addr);
+
+               err = ionic_program_mac(lif, mac_address);
+               if (err < 0)
+                       return err;
+
+               if (err > 0) {
+                       netdev_dbg(netdev, "%s:SET/GET ATTR Mac are not same-due to old FW running\n",
+                                  __func__);
+                       return 0;
+               }
+       }
 
        if (!is_zero_ether_addr(netdev->dev_addr)) {
                /* If the netdev mac is non-zero and doesn't match the default
@@ -3189,12 +3272,11 @@ static int ionic_station_set(struct ionic_lif *lif)
                 * likely here again after a fw-upgrade reset.  We need to be
                 * sure the netdev mac is in our filter list.
                 */
-               if (!ether_addr_equal(ctx.comp.lif_getattr.mac,
-                                     netdev->dev_addr))
+               if (!ether_addr_equal(mac_address, netdev->dev_addr))
                        ionic_lif_addr_add(lif, netdev->dev_addr);
        } else {
                /* Update the netdev mac with the device's mac */
-               memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
+               ether_addr_copy(addr.sa_data, mac_address);
                addr.sa_family = AF_INET;
                err = eth_prepare_mac_addr_change(netdev, &addr);
                if (err) {