Skip to content

Commit

Permalink
Merge branch 'ionic-locking-and-filter-fixes'
Browse files Browse the repository at this point in the history
Shannon Nelson says:

====================
ionic: locking and filter fixes

These patches address an ethtool show regs problem, some locking sightings,
and issues with RSS hash and filter_id tracking after a managed FW update.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 21, 2020
2 parents 5d93518 + 0925e9d commit 4932893
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 40 deletions.
7 changes: 5 additions & 2 deletions drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,18 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
void *p)
{
struct ionic_lif *lif = netdev_priv(netdev);
unsigned int offset;
unsigned int size;

regs->version = IONIC_DEV_CMD_REG_VERSION;

offset = 0;
size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
memcpy_fromio(p, lif->ionic->idev.dev_info_regs->words, size);
memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);

offset += size;
size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
memcpy_fromio(p, lif->ionic->idev.dev_cmd_regs->words, size);
memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
}

static int ionic_get_link_ksettings(struct net_device *netdev,
Expand Down
50 changes: 25 additions & 25 deletions drivers/net/ethernet/pensando/ionic/ionic_lif.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
u16 link_status;
bool link_up;

if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state) ||
test_bit(IONIC_LIF_F_QUEUE_RESET, lif->state))
if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state))
return;

link_status = le16_to_cpu(lif->info->status.link_status);
Expand All @@ -114,16 +113,22 @@ static void ionic_link_status_check(struct ionic_lif *lif)
netif_carrier_on(netdev);
}

if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
mutex_lock(&lif->queue_lock);
ionic_start_queues(lif);
mutex_unlock(&lif->queue_lock);
}
} else {
if (netif_carrier_ok(netdev)) {
netdev_info(netdev, "Link down\n");
netif_carrier_off(netdev);
}

if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
mutex_lock(&lif->queue_lock);
ionic_stop_queues(lif);
mutex_unlock(&lif->queue_lock);
}
}

clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
Expand Down Expand Up @@ -863,8 +868,7 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
if (f)
return 0;

netdev_dbg(lif->netdev, "rx_filter add ADDR %pM (id %d)\n", addr,
ctx.comp.rx_filter_add.filter_id);
netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr);

memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN);
err = ionic_adminq_post_wait(lif, &ctx);
Expand Down Expand Up @@ -893,6 +897,9 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
return -ENOENT;
}

netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n",
addr, f->filter_id);

ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
ionic_rx_filter_free(lif, f);
spin_unlock_bh(&lif->rx_filters.lock);
Expand All @@ -901,9 +908,6 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
if (err && err != -EEXIST)
return err;

netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr,
ctx.cmd.rx_filter_del.filter_id);

return 0;
}

Expand Down Expand Up @@ -1351,13 +1355,11 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
};
int err;

netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
err = ionic_adminq_post_wait(lif, &ctx);
if (err)
return err;

netdev_dbg(netdev, "rx_filter add VLAN %d (id %d)\n", vid,
ctx.comp.rx_filter_add.filter_id);

return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx);
}

Expand All @@ -1382,8 +1384,8 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
return -ENOENT;
}

netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", vid,
le32_to_cpu(ctx.cmd.rx_filter_del.filter_id));
netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
vid, f->filter_id);

ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
ionic_rx_filter_free(lif, f);
Expand Down Expand Up @@ -1993,16 +1995,13 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
bool running;
int err = 0;

err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET);
if (err)
return err;

mutex_lock(&lif->queue_lock);
running = netif_running(lif->netdev);
if (running) {
netif_device_detach(lif->netdev);
err = ionic_stop(lif->netdev);
if (err)
goto reset_out;
return err;
}

if (cb)
Expand All @@ -2012,9 +2011,7 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
err = ionic_open(lif->netdev);
netif_device_attach(lif->netdev);
}

reset_out:
clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
mutex_unlock(&lif->queue_lock);

return err;
}
Expand Down Expand Up @@ -2161,7 +2158,9 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif)

if (test_bit(IONIC_LIF_F_UP, lif->state)) {
dev_info(ionic->dev, "Surprise FW stop, stopping queues\n");
mutex_lock(&lif->queue_lock);
ionic_stop_queues(lif);
mutex_unlock(&lif->queue_lock);
}

if (netif_running(lif->netdev)) {
Expand Down Expand Up @@ -2280,15 +2279,15 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
cancel_work_sync(&lif->deferred.work);
cancel_work_sync(&lif->tx_timeout_work);
ionic_rx_filters_deinit(lif);
if (lif->netdev->features & NETIF_F_RXHASH)
ionic_lif_rss_deinit(lif);
}

if (lif->netdev->features & NETIF_F_RXHASH)
ionic_lif_rss_deinit(lif);

napi_disable(&lif->adminqcq->napi);
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
ionic_lif_qcq_deinit(lif, lif->adminqcq);

mutex_destroy(&lif->queue_lock);
ionic_lif_reset(lif);
}

Expand Down Expand Up @@ -2465,6 +2464,7 @@ static int ionic_lif_init(struct ionic_lif *lif)
return err;

lif->hw_index = le16_to_cpu(comp.hw_index);
mutex_init(&lif->queue_lock);

/* now that we have the hw_index we can figure out our doorbell page */
lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
Expand Down
8 changes: 1 addition & 7 deletions drivers/net/ethernet/pensando/ionic/ionic_lif.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ enum ionic_lif_state_flags {
IONIC_LIF_F_SW_DEBUG_STATS,
IONIC_LIF_F_UP,
IONIC_LIF_F_LINK_CHECK_REQUESTED,
IONIC_LIF_F_QUEUE_RESET,
IONIC_LIF_F_FW_RESET,

/* leave this as last */
Expand Down Expand Up @@ -165,6 +164,7 @@ struct ionic_lif {
unsigned int hw_index;
unsigned int kern_pid;
u64 __iomem *kern_dbpage;
struct mutex queue_lock; /* lock for queue structures */
spinlock_t adminq_lock; /* lock for AdminQ operations */
struct ionic_qcq *adminqcq;
struct ionic_qcq *notifyqcq;
Expand Down Expand Up @@ -213,12 +213,6 @@ struct ionic_lif {
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)

/* return 0 if successfully set the bit, else non-zero */
static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
{
return wait_on_bit_lock(lif->state, bitname, TASK_INTERRUPTIBLE);
}

static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
{
u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult);
Expand Down
29 changes: 29 additions & 0 deletions drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
void ionic_rx_filter_replay(struct ionic_lif *lif)
{
struct ionic_rx_filter_add_cmd *ac;
struct hlist_head new_id_list;
struct ionic_admin_ctx ctx;
struct ionic_rx_filter *f;
struct hlist_head *head;
struct hlist_node *tmp;
unsigned int key;
unsigned int i;
int err;

INIT_HLIST_HEAD(&new_id_list);
ac = &ctx.cmd.rx_filter_add;

for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
Expand Down Expand Up @@ -58,9 +61,30 @@ void ionic_rx_filter_replay(struct ionic_lif *lif)
ac->mac.addr);
break;
}
spin_lock_bh(&lif->rx_filters.lock);
ionic_rx_filter_free(lif, f);
spin_unlock_bh(&lif->rx_filters.lock);

continue;
}

/* remove from old id list, save new id in tmp list */
spin_lock_bh(&lif->rx_filters.lock);
hlist_del(&f->by_id);
spin_unlock_bh(&lif->rx_filters.lock);
f->filter_id = le32_to_cpu(ctx.comp.rx_filter_add.filter_id);
hlist_add_head(&f->by_id, &new_id_list);
}
}

/* rebuild the by_id hash lists with the new filter ids */
spin_lock_bh(&lif->rx_filters.lock);
hlist_for_each_entry_safe(f, tmp, &new_id_list, by_id) {
key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
head = &lif->rx_filters.by_id[key];
hlist_add_head(&f->by_id, head);
}
spin_unlock_bh(&lif->rx_filters.lock);
}

int ionic_rx_filters_init(struct ionic_lif *lif)
Expand All @@ -69,10 +93,12 @@ int ionic_rx_filters_init(struct ionic_lif *lif)

spin_lock_init(&lif->rx_filters.lock);

spin_lock_bh(&lif->rx_filters.lock);
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
}
spin_unlock_bh(&lif->rx_filters.lock);

return 0;
}
Expand All @@ -84,11 +110,13 @@ void ionic_rx_filters_deinit(struct ionic_lif *lif)
struct hlist_node *tmp;
unsigned int i;

spin_lock_bh(&lif->rx_filters.lock);
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)
ionic_rx_filter_free(lif, f);
}
spin_unlock_bh(&lif->rx_filters.lock);
}

int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
Expand Down Expand Up @@ -124,6 +152,7 @@ int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
f->rxq_index = rxq_index;
memcpy(&f->cmd, ac, sizeof(f->cmd));
netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id);

INIT_HLIST_NODE(&f->by_hash);
INIT_HLIST_NODE(&f->by_id);
Expand Down
6 changes: 0 additions & 6 deletions drivers/net/ethernet/pensando/ionic/ionic_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,6 @@ static void ionic_rx_clean(struct ionic_queue *q,
return;
}

/* no packet processing while resetting */
if (unlikely(test_bit(IONIC_LIF_F_QUEUE_RESET, q->lif->state))) {
stats->dropped++;
return;
}

stats->pkts++;
stats->bytes += le16_to_cpu(comp->len);

Expand Down

0 comments on commit 4932893

Please sign in to comment.