Commit 7e4d4759 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller
Browse files

ionic: replay filters after fw upgrade



The NIC's filters are lost in the midst of the fw-upgrade
so we need to replay them into the FW.  We also remove the
unused ionic_rx_filter_del() function.

Fixes: c672412f ("ionic: remove lifs on fw reset")
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb9533d1
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -2127,6 +2127,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
	if (lif->registered)
		ionic_lif_set_netdev_info(lif);

	ionic_rx_filter_replay(lif);

	if (netif_running(lif->netdev)) {
		err = ionic_txrx_alloc(lif);
		if (err)
@@ -2206,9 +2208,9 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
	if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
		cancel_work_sync(&lif->deferred.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)
		ionic_lif_rss_deinit(lif);

@@ -2421,9 +2423,11 @@ static int ionic_lif_init(struct ionic_lif *lif)
	if (err)
		goto err_out_notifyq_deinit;

	if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
		err = ionic_rx_filters_init(lif);
		if (err)
			goto err_out_notifyq_deinit;
	}

	err = ionic_station_set(lif);
	if (err)
+42 −10
Original line number Diff line number Diff line
@@ -17,17 +17,49 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *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 = {
		.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
		.cmd.rx_filter_del = {
			.opcode = IONIC_CMD_RX_FILTER_DEL,
			.filter_id = cpu_to_le32(f->filter_id),
		},
	};

	return ionic_adminq_post_wait(lif, &ctx);
	struct ionic_rx_filter_add_cmd *ac;
	struct ionic_admin_ctx ctx;
	struct ionic_rx_filter *f;
	struct hlist_head *head;
	struct hlist_node *tmp;
	unsigned int i;
	int err = 0;

	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)
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ struct ionic_rx_filters {
};

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);
void ionic_rx_filters_deinit(struct ionic_lif *lif);
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,