Merge branch 'ionic-bug-fixes'
Shannon Nelson says: ==================== ionic: bug fixes These are a couple of maintenance bug fixes for the Pensando ionic networking driver. Mohamed takes care of a "plays well with others" issue where the VF spec is a bit vague on VF mac addresses, but certain customers have come to expect behavior based on other vendor drivers. Shannon addresses a couple of corner cases seen in internal stress testing. ==================== Link: https://lore.kernel.org/r/20220824165051.6185-1-snelson@pensando.io Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
92df825ad2
|
@ -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;
|
||||
|
@ -2963,6 +3030,9 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
|
|||
|
||||
mutex_lock(&lif->queue_lock);
|
||||
|
||||
if (test_and_clear_bit(IONIC_LIF_F_BROKEN, lif->state))
|
||||
dev_info(ionic->dev, "FW Up: clearing broken state\n");
|
||||
|
||||
err = ionic_qcqs_alloc(lif);
|
||||
if (err)
|
||||
goto err_unlock;
|
||||
|
@ -3169,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;
|
||||
|
||||
|
@ -3177,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
|
||||
|
@ -3186,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) {
|
||||
|
|
|
@ -474,8 +474,8 @@ try_again:
|
|||
ionic_opcode_to_str(opcode), opcode,
|
||||
ionic_error_to_str(err), err);
|
||||
|
||||
msleep(1000);
|
||||
iowrite32(0, &idev->dev_cmd_regs->done);
|
||||
msleep(1000);
|
||||
iowrite32(1, &idev->dev_cmd_regs->doorbell);
|
||||
goto try_again;
|
||||
}
|
||||
|
@ -488,6 +488,8 @@ try_again:
|
|||
return ionic_error_to_errno(err);
|
||||
}
|
||||
|
||||
ionic_dev_cmd_clean(ionic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче