Commit 48fc96b3 authored by David S. Miller's avatar David S. Miller

Merge branch 'ionic-fw-upgrade-filter-fixes'

Shannon Nelson says:

====================
ionic: fw upgrade filter fixes

With further testing of the fw-upgrade operations we found a
couple of issues that needed to be cleaned up:
 - the filters other than the base MAC address need to be
   reinstated into the device
 - we don't need to remove the station MAC filter if it
   isn't changing from a previous MAC filter
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cb9533d1 216902ae
...@@ -2127,6 +2127,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) ...@@ -2127,6 +2127,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
if (lif->registered) if (lif->registered)
ionic_lif_set_netdev_info(lif); ionic_lif_set_netdev_info(lif);
ionic_rx_filter_replay(lif);
if (netif_running(lif->netdev)) { if (netif_running(lif->netdev)) {
err = ionic_txrx_alloc(lif); err = ionic_txrx_alloc(lif);
if (err) if (err)
...@@ -2206,9 +2208,9 @@ static void ionic_lif_deinit(struct ionic_lif *lif) ...@@ -2206,9 +2208,9 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
cancel_work_sync(&lif->deferred.work); cancel_work_sync(&lif->deferred.work);
cancel_work_sync(&lif->tx_timeout_work); cancel_work_sync(&lif->tx_timeout_work);
ionic_rx_filters_deinit(lif);
} }
ionic_rx_filters_deinit(lif);
if (lif->netdev->features & NETIF_F_RXHASH) if (lif->netdev->features & NETIF_F_RXHASH)
ionic_lif_rss_deinit(lif); ionic_lif_rss_deinit(lif);
...@@ -2339,24 +2341,30 @@ static int ionic_station_set(struct ionic_lif *lif) ...@@ -2339,24 +2341,30 @@ static int ionic_station_set(struct ionic_lif *lif)
err = ionic_adminq_post_wait(lif, &ctx); err = ionic_adminq_post_wait(lif, &ctx);
if (err) if (err)
return err; 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)) if (is_zero_ether_addr(ctx.comp.lif_getattr.mac))
return 0; return 0;
memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len); if (!ether_addr_equal(ctx.comp.lif_getattr.mac, netdev->dev_addr)) {
addr.sa_family = AF_INET; memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
err = eth_prepare_mac_addr_change(netdev, &addr); addr.sa_family = AF_INET;
if (err) { err = eth_prepare_mac_addr_change(netdev, &addr);
netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM - err %d\n", if (err) {
addr.sa_data, err); netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM - err %d\n",
return 0; addr.sa_data, err);
} return 0;
}
netdev_dbg(lif->netdev, "deleting station MAC addr %pM\n", if (!is_zero_ether_addr(netdev->dev_addr)) {
netdev->dev_addr); netdev_dbg(lif->netdev, "deleting station MAC addr %pM\n",
ionic_lif_addr(lif, netdev->dev_addr, false); netdev->dev_addr);
ionic_lif_addr(lif, netdev->dev_addr, false);
}
eth_commit_mac_addr_change(netdev, &addr);
}
eth_commit_mac_addr_change(netdev, &addr);
netdev_dbg(lif->netdev, "adding station MAC addr %pM\n", netdev_dbg(lif->netdev, "adding station MAC addr %pM\n",
netdev->dev_addr); netdev->dev_addr);
ionic_lif_addr(lif, netdev->dev_addr, true); ionic_lif_addr(lif, netdev->dev_addr, true);
...@@ -2421,9 +2429,11 @@ static int ionic_lif_init(struct ionic_lif *lif) ...@@ -2421,9 +2429,11 @@ static int ionic_lif_init(struct ionic_lif *lif)
if (err) if (err)
goto err_out_notifyq_deinit; goto err_out_notifyq_deinit;
err = ionic_rx_filters_init(lif); if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
if (err) err = ionic_rx_filters_init(lif);
goto err_out_notifyq_deinit; if (err)
goto err_out_notifyq_deinit;
}
err = ionic_station_set(lif); err = ionic_station_set(lif);
if (err) if (err)
......
...@@ -17,17 +17,49 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f) ...@@ -17,17 +17,49 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
devm_kfree(dev, f); devm_kfree(dev, f);
} }
int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f) void ionic_rx_filter_replay(struct ionic_lif *lif)
{ {
struct ionic_admin_ctx ctx = { struct ionic_rx_filter_add_cmd *ac;
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), struct ionic_admin_ctx ctx;
.cmd.rx_filter_del = { struct ionic_rx_filter *f;
.opcode = IONIC_CMD_RX_FILTER_DEL, struct hlist_head *head;
.filter_id = cpu_to_le32(f->filter_id), struct hlist_node *tmp;
}, unsigned int i;
}; int err = 0;
return ionic_adminq_post_wait(lif, &ctx); ac = &ctx.cmd.rx_filter_add;
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
head = &lif->rx_filters.by_id[i];
hlist_for_each_entry_safe(f, tmp, head, by_id) {
ctx.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work);
memcpy(ac, &f->cmd, sizeof(f->cmd));
dev_dbg(&lif->netdev->dev, "replay filter command:\n");
dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
&ctx.cmd, sizeof(ctx.cmd), true);
err = ionic_adminq_post_wait(lif, &ctx);
if (err) {
switch (le16_to_cpu(ac->match)) {
case IONIC_RX_FILTER_MATCH_VLAN:
netdev_info(lif->netdev, "Replay failed - %d: vlan %d\n",
err,
le16_to_cpu(ac->vlan.vlan));
break;
case IONIC_RX_FILTER_MATCH_MAC:
netdev_info(lif->netdev, "Replay failed - %d: mac %pM\n",
err, ac->mac.addr);
break;
case IONIC_RX_FILTER_MATCH_MAC_VLAN:
netdev_info(lif->netdev, "Replay failed - %d: vlan %d mac %pM\n",
err,
le16_to_cpu(ac->vlan.vlan),
ac->mac.addr);
break;
}
}
}
}
} }
int ionic_rx_filters_init(struct ionic_lif *lif) int ionic_rx_filters_init(struct ionic_lif *lif)
......
...@@ -24,7 +24,7 @@ struct ionic_rx_filters { ...@@ -24,7 +24,7 @@ struct ionic_rx_filters {
}; };
void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f); void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f);
int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f); void ionic_rx_filter_replay(struct ionic_lif *lif);
int ionic_rx_filters_init(struct ionic_lif *lif); int ionic_rx_filters_init(struct ionic_lif *lif);
void ionic_rx_filters_deinit(struct ionic_lif *lif); void ionic_rx_filters_deinit(struct ionic_lif *lif);
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index, int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment