diff options
Diffstat (limited to 'drivers/net/ethernet/pensando')
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_debugfs.c | 48 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_dev.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_dev.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_devlink.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_ethtool.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_lif.c | 264 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_lif.h | 49 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_main.c | 92 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_phc.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c | 241 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_stats.c | 121 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 14 |
14 files changed, 433 insertions, 470 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h index 66204106f83e..5e25411ff02f 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic.h +++ b/drivers/net/ethernet/pensando/ionic/ionic.h @@ -19,6 +19,7 @@ struct ionic_lif; #define PCI_DEVICE_ID_PENSANDO_IONIC_ETH_VF 0x1003 #define DEVCMD_TIMEOUT 10 +#define IONIC_ADMINQ_TIME_SLICE msecs_to_jiffies(100) #define IONIC_PHC_UPDATE_NS 10000000000 /* 10s in nanoseconds */ #define NORMAL_PPB 1000000000 /* one billion parts per billion */ @@ -69,8 +70,13 @@ struct ionic_admin_ctx { }; int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx); -int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, int err); +int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, + const int err, const bool do_msg); int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx); +int ionic_adminq_post_wait_nomsg(struct ionic_lif *lif, struct ionic_admin_ctx *ctx); +void ionic_adminq_netdev_err_print(struct ionic_lif *lif, u8 opcode, + u8 status, int err); + int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait); int ionic_set_dma_mask(struct ionic *ionic); int ionic_setup(struct ionic *ionic); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c index 39f59849720d..c58217027564 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c @@ -143,8 +143,6 @@ void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq) debugfs_create_u32("qid", 0400, q_dentry, &q->hw_index); debugfs_create_u32("qtype", 0400, q_dentry, &q->hw_type); debugfs_create_u64("drop", 0400, q_dentry, &q->drop); - debugfs_create_u64("stop", 0400, q_dentry, &q->stop); - debugfs_create_u64("wake", 0400, q_dentry, &q->wake); debugfs_create_file("tail", 0400, q_dentry, q, &q_tail_fops); debugfs_create_file("head", 0400, q_dentry, q, &q_head_fops); @@ -228,6 +226,50 @@ static int netdev_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(netdev); +static int lif_filters_show(struct seq_file *seq, void *v) +{ + struct ionic_lif *lif = seq->private; + struct ionic_rx_filter *f; + struct hlist_head *head; + struct hlist_node *tmp; + unsigned int i; + + seq_puts(seq, "id flow state type filter\n"); + 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) { + switch (le16_to_cpu(f->cmd.match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + seq_printf(seq, "0x%04x 0x%08x 0x%02x vlan 0x%04x\n", + f->filter_id, f->flow_id, f->state, + le16_to_cpu(f->cmd.vlan.vlan)); + break; + case IONIC_RX_FILTER_MATCH_MAC: + seq_printf(seq, "0x%04x 0x%08x 0x%02x mac %pM\n", + f->filter_id, f->flow_id, f->state, + f->cmd.mac.addr); + break; + case IONIC_RX_FILTER_MATCH_MAC_VLAN: + seq_printf(seq, "0x%04x 0x%08x 0x%02x macvl 0x%04x %pM\n", + f->filter_id, f->flow_id, f->state, + le16_to_cpu(f->cmd.vlan.vlan), + f->cmd.mac.addr); + break; + case IONIC_RX_FILTER_STEER_PKTCLASS: + seq_printf(seq, "0x%04x 0x%08x 0x%02x rxstr 0x%llx\n", + f->filter_id, f->flow_id, f->state, + le64_to_cpu(f->cmd.pkt_class)); + break; + } + } + } + spin_unlock_bh(&lif->rx_filters.lock); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(lif_filters); + void ionic_debugfs_add_lif(struct ionic_lif *lif) { struct dentry *lif_dentry; @@ -239,6 +281,8 @@ void ionic_debugfs_add_lif(struct ionic_lif *lif) debugfs_create_file("netdev", 0400, lif->dentry, lif->netdev, &netdev_fops); + debugfs_create_file("filters", 0400, lif->dentry, + lif, &lif_filters_fops); } void ionic_debugfs_del_lif(struct ionic_lif *lif) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c index 0d6858ab511c..d57e80d44c9d 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c @@ -581,7 +581,6 @@ unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do, cq->done_color = !cq->done_color; cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1); cq_info = &cq->info[cq->tail_idx]; - DEBUG_STATS_CQE_CNT(cq); if (++work_done >= work_to_do) break; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h index 8311086fb1f4..e5acf3bd62b2 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h @@ -220,9 +220,6 @@ struct ionic_queue { unsigned int num_descs; unsigned int max_sg_elems; u64 features; - u64 dbell_count; - u64 stop; - u64 wake; u64 drop; struct ionic_dev *idev; unsigned int type; @@ -269,7 +266,6 @@ struct ionic_cq { bool done_color; unsigned int num_descs; unsigned int desc_size; - u64 compl_count; void *base; dma_addr_t base_pa; } ____cacheline_aligned_in_smp; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_devlink.c b/drivers/net/ethernet/pensando/ionic/ionic_devlink.c index c7d0e195d176..4297ed9024c0 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_devlink.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_devlink.c @@ -82,22 +82,16 @@ int ionic_devlink_register(struct ionic *ionic) struct devlink_port_attrs attrs = {}; int err; - err = devlink_register(dl); - if (err) { - dev_warn(ionic->dev, "devlink_register failed: %d\n", err); - return err; - } - attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; devlink_port_attrs_set(&ionic->dl_port, &attrs); err = devlink_port_register(dl, &ionic->dl_port, 0); if (err) { dev_err(ionic->dev, "devlink_port_register failed: %d\n", err); - devlink_unregister(dl); return err; } devlink_port_type_eth_set(&ionic->dl_port, ionic->lif->netdev); + devlink_register(dl); return 0; } @@ -105,6 +99,6 @@ void ionic_devlink_unregister(struct ionic *ionic) { struct devlink *dl = priv_to_devlink(ionic); - devlink_port_unregister(&ionic->dl_port); devlink_unregister(dl); + devlink_port_unregister(&ionic->dl_port); } diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 3de1a03839e2..c54d735b9e2e 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -11,13 +11,6 @@ #include "ionic_ethtool.h" #include "ionic_stats.h" -static const char ionic_priv_flags_strings[][ETH_GSTRING_LEN] = { -#define IONIC_PRIV_F_SW_DBG_STATS BIT(0) - "sw-dbg-stats", -}; - -#define IONIC_PRIV_FLAGS_COUNT ARRAY_SIZE(ionic_priv_flags_strings) - static void ionic_get_stats_strings(struct ionic_lif *lif, u8 *buf) { u32 i; @@ -59,9 +52,6 @@ static int ionic_get_sset_count(struct net_device *netdev, int sset) case ETH_SS_STATS: count = ionic_get_stats_count(lif); break; - case ETH_SS_PRIV_FLAGS: - count = IONIC_PRIV_FLAGS_COUNT; - break; } return count; } @@ -75,10 +65,6 @@ static void ionic_get_strings(struct net_device *netdev, case ETH_SS_STATS: ionic_get_stats_strings(lif, buf); break; - case ETH_SS_PRIV_FLAGS: - memcpy(buf, ionic_priv_flags_strings, - IONIC_PRIV_FLAGS_COUNT * ETH_GSTRING_LEN); - break; } } @@ -228,8 +214,7 @@ static int ionic_get_link_ksettings(struct net_device *netdev, break; } - bitmap_copy(ks->link_modes.advertising, ks->link_modes.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_copy(ks->link_modes.advertising, ks->link_modes.supported); ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); @@ -691,28 +676,6 @@ static int ionic_set_channels(struct net_device *netdev, return err; } -static u32 ionic_get_priv_flags(struct net_device *netdev) -{ - struct ionic_lif *lif = netdev_priv(netdev); - u32 priv_flags = 0; - - if (test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) - priv_flags |= IONIC_PRIV_F_SW_DBG_STATS; - - return priv_flags; -} - -static int ionic_set_priv_flags(struct net_device *netdev, u32 priv_flags) -{ - struct ionic_lif *lif = netdev_priv(netdev); - - clear_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state); - if (priv_flags & IONIC_PRIV_F_SW_DBG_STATS) - set_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state); - - return 0; -} - static int ionic_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, u32 *rules) { @@ -1013,8 +976,6 @@ static const struct ethtool_ops ionic_ethtool_ops = { .get_strings = ionic_get_strings, .get_ethtool_stats = ionic_get_stats, .get_sset_count = ionic_get_sset_count, - .get_priv_flags = ionic_get_priv_flags, - .set_priv_flags = ionic_set_priv_flags, .get_rxnfc = ionic_get_rxnfc, .get_rxfh_indir_size = ionic_get_rxfh_indir_size, .get_rxfh_key_size = ionic_get_rxfh_key_size, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 7f3322ce044c..63f8a8163b5f 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -287,11 +287,9 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) return ionic_adminq_post_wait(lif, &ctx); } -static int ionic_qcq_disable(struct ionic_qcq *qcq, bool send_to_hw) +static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int fw_err) { struct ionic_queue *q; - struct ionic_lif *lif; - int err = 0; struct ionic_admin_ctx ctx = { .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), @@ -301,11 +299,12 @@ static int ionic_qcq_disable(struct ionic_qcq *qcq, bool send_to_hw) }, }; - if (!qcq) + if (!qcq) { + netdev_err(lif->netdev, "%s: bad qcq\n", __func__); return -ENXIO; + } q = &qcq->q; - lif = q->lif; if (qcq->flags & IONIC_QCQ_F_INTR) { struct ionic_dev *idev = &lif->ionic->idev; @@ -318,17 +317,19 @@ static int ionic_qcq_disable(struct ionic_qcq *qcq, bool send_to_hw) napi_disable(&qcq->napi); } - if (send_to_hw) { - ctx.cmd.q_control.lif_index = cpu_to_le16(lif->index); - ctx.cmd.q_control.type = q->type; - ctx.cmd.q_control.index = cpu_to_le32(q->index); - dev_dbg(lif->ionic->dev, "q_disable.index %d q_disable.qtype %d\n", - ctx.cmd.q_control.index, ctx.cmd.q_control.type); + /* If there was a previous fw communcation error, don't bother with + * sending the adminq command and just return the same error value. + */ + if (fw_err == -ETIMEDOUT || fw_err == -ENXIO) + return fw_err; - err = ionic_adminq_post_wait(lif, &ctx); - } + ctx.cmd.q_control.lif_index = cpu_to_le16(lif->index); + ctx.cmd.q_control.type = q->type; + ctx.cmd.q_control.index = cpu_to_le32(q->index); + dev_dbg(lif->ionic->dev, "q_disable.index %d q_disable.qtype %d\n", + ctx.cmd.q_control.index, ctx.cmd.q_control.type); - return err; + return ionic_adminq_post_wait(lif, &ctx); } static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) @@ -1241,137 +1242,6 @@ void ionic_get_stats64(struct net_device *netdev, ns->tx_errors = ns->tx_aborted_errors; } -int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) -{ - struct ionic_admin_ctx ctx = { - .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), - .cmd.rx_filter_add = { - .opcode = IONIC_CMD_RX_FILTER_ADD, - .lif_index = cpu_to_le16(lif->index), - .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_MAC), - }, - }; - int nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters); - bool mc = is_multicast_ether_addr(addr); - struct ionic_rx_filter *f; - int err = 0; - - memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN); - - spin_lock_bh(&lif->rx_filters.lock); - f = ionic_rx_filter_by_addr(lif, addr); - if (f) { - /* don't bother if we already have it and it is sync'd */ - if (f->state == IONIC_FILTER_STATE_SYNCED) { - spin_unlock_bh(&lif->rx_filters.lock); - return 0; - } - - /* mark preemptively as sync'd to block any parallel attempts */ - f->state = IONIC_FILTER_STATE_SYNCED; - } else { - /* save as SYNCED to catch any DEL requests while processing */ - err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, - IONIC_FILTER_STATE_SYNCED); - } - spin_unlock_bh(&lif->rx_filters.lock); - if (err) - return err; - - netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr); - - /* Don't bother with the write to FW if we know there's no room, - * we can try again on the next sync attempt. - */ - if ((lif->nucast + lif->nmcast) >= nfilters) - err = -ENOSPC; - else - err = ionic_adminq_post_wait(lif, &ctx); - - spin_lock_bh(&lif->rx_filters.lock); - if (err && err != -EEXIST) { - /* set the state back to NEW so we can try again later */ - f = ionic_rx_filter_by_addr(lif, addr); - if (f && f->state == IONIC_FILTER_STATE_SYNCED) { - f->state = IONIC_FILTER_STATE_NEW; - set_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state); - } - - spin_unlock_bh(&lif->rx_filters.lock); - - if (err == -ENOSPC) - return 0; - else - return err; - } - - if (mc) - lif->nmcast++; - else - lif->nucast++; - - f = ionic_rx_filter_by_addr(lif, addr); - if (f && f->state == IONIC_FILTER_STATE_OLD) { - /* Someone requested a delete while we were adding - * so update the filter info with the results from the add - * and the data will be there for the delete on the next - * sync cycle. - */ - err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, - IONIC_FILTER_STATE_OLD); - } else { - err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, - IONIC_FILTER_STATE_SYNCED); - } - - spin_unlock_bh(&lif->rx_filters.lock); - - return err; -} - -int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) -{ - struct ionic_admin_ctx ctx = { - .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), - .cmd.rx_filter_del = { - .opcode = IONIC_CMD_RX_FILTER_DEL, - .lif_index = cpu_to_le16(lif->index), - }, - }; - struct ionic_rx_filter *f; - int state; - int err; - - spin_lock_bh(&lif->rx_filters.lock); - f = ionic_rx_filter_by_addr(lif, addr); - if (!f) { - spin_unlock_bh(&lif->rx_filters.lock); - return -ENOENT; - } - - netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", - addr, f->filter_id); - - state = f->state; - ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id); - ionic_rx_filter_free(lif, f); - - if (is_multicast_ether_addr(addr) && lif->nmcast) - lif->nmcast--; - else if (!is_multicast_ether_addr(addr) && lif->nucast) - lif->nucast--; - - spin_unlock_bh(&lif->rx_filters.lock); - - if (state != IONIC_FILTER_STATE_NEW) { - err = ionic_adminq_post_wait(lif, &ctx); - if (err && err != -EEXIST) - return err; - } - - return 0; -} - static int ionic_addr_add(struct net_device *netdev, const u8 *addr) { return ionic_lif_list_addr(netdev_priv(netdev), addr, ADD_ADDR); @@ -1407,7 +1277,7 @@ void ionic_lif_rx_mode(struct ionic_lif *lif) rx_mode |= (nd_flags & IFF_PROMISC) ? IONIC_RX_MODE_F_PROMISC : 0; rx_mode |= (nd_flags & IFF_ALLMULTI) ? IONIC_RX_MODE_F_ALLMULTI : 0; - /* sync the mac filters */ + /* sync the filters */ ionic_rx_filter_sync(lif); /* check for overflow state @@ -1417,14 +1287,12 @@ void ionic_lif_rx_mode(struct ionic_lif *lif) * to see if we can disable NIC PROMISC */ nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters); - if ((lif->nucast + lif->nmcast) >= nfilters) { + + if (((lif->nucast + lif->nmcast) >= nfilters) || + (lif->max_vlans && lif->nvlans >= lif->max_vlans)) { rx_mode |= IONIC_RX_MODE_F_PROMISC; rx_mode |= IONIC_RX_MODE_F_ALLMULTI; - lif->uc_overflow = true; - lif->mc_overflow = true; - } else if (lif->uc_overflow) { - lif->uc_overflow = false; - lif->mc_overflow = false; + } else { if (!(nd_flags & IFF_PROMISC)) rx_mode &= ~IONIC_RX_MODE_F_PROMISC; if (!(nd_flags & IFF_ALLMULTI)) @@ -1809,59 +1677,30 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) { struct ionic_lif *lif = netdev_priv(netdev); - struct ionic_admin_ctx ctx = { - .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), - .cmd.rx_filter_add = { - .opcode = IONIC_CMD_RX_FILTER_ADD, - .lif_index = cpu_to_le16(lif->index), - .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN), - .vlan.vlan = cpu_to_le16(vid), - }, - }; int err; - netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid); - err = ionic_adminq_post_wait(lif, &ctx); + err = ionic_lif_vlan_add(lif, vid); if (err) return err; - spin_lock_bh(&lif->rx_filters.lock); - err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, - IONIC_FILTER_STATE_SYNCED); - spin_unlock_bh(&lif->rx_filters.lock); + ionic_lif_rx_mode(lif); - return err; + return 0; } static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) { struct ionic_lif *lif = netdev_priv(netdev); - struct ionic_admin_ctx ctx = { - .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), - .cmd.rx_filter_del = { - .opcode = IONIC_CMD_RX_FILTER_DEL, - .lif_index = cpu_to_le16(lif->index), - }, - }; - struct ionic_rx_filter *f; - - spin_lock_bh(&lif->rx_filters.lock); - - f = ionic_rx_filter_by_vlan(lif, vid); - if (!f) { - spin_unlock_bh(&lif->rx_filters.lock); - return -ENOENT; - } + int err; - netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", - vid, f->filter_id); + err = ionic_lif_vlan_del(lif, vid); + if (err) + return err; - 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); + ionic_lif_rx_mode(lif); - return ionic_adminq_post_wait(lif, &ctx); + return 0; } int ionic_lif_rss_config(struct ionic_lif *lif, const u16 types, @@ -1953,19 +1792,19 @@ static void ionic_txrx_disable(struct ionic_lif *lif) if (lif->txqcqs) { for (i = 0; i < lif->nxqs; i++) - err = ionic_qcq_disable(lif->txqcqs[i], (err != -ETIMEDOUT)); + err = ionic_qcq_disable(lif, lif->txqcqs[i], err); } if (lif->hwstamp_txq) - err = ionic_qcq_disable(lif->hwstamp_txq, (err != -ETIMEDOUT)); + err = ionic_qcq_disable(lif, lif->hwstamp_txq, err); if (lif->rxqcqs) { for (i = 0; i < lif->nxqs; i++) - err = ionic_qcq_disable(lif->rxqcqs[i], (err != -ETIMEDOUT)); + err = ionic_qcq_disable(lif, lif->rxqcqs[i], err); } if (lif->hwstamp_rxq) - err = ionic_qcq_disable(lif->hwstamp_rxq, (err != -ETIMEDOUT)); + err = ionic_qcq_disable(lif, lif->hwstamp_rxq, err); ionic_lif_quiesce(lif); } @@ -2165,7 +2004,7 @@ static int ionic_txrx_enable(struct ionic_lif *lif) err = ionic_qcq_enable(lif->txqcqs[i]); if (err) { - derr = ionic_qcq_disable(lif->rxqcqs[i], (err != -ETIMEDOUT)); + derr = ionic_qcq_disable(lif, lif->rxqcqs[i], err); goto err_out; } } @@ -2187,13 +2026,13 @@ static int ionic_txrx_enable(struct ionic_lif *lif) err_out_hwstamp_tx: if (lif->hwstamp_rxq) - derr = ionic_qcq_disable(lif->hwstamp_rxq, (derr != -ETIMEDOUT)); + derr = ionic_qcq_disable(lif, lif->hwstamp_rxq, derr); err_out_hwstamp_rx: i = lif->nxqs; err_out: while (i--) { - derr = ionic_qcq_disable(lif->txqcqs[i], (derr != -ETIMEDOUT)); - derr = ionic_qcq_disable(lif->rxqcqs[i], (derr != -ETIMEDOUT)); + derr = ionic_qcq_disable(lif, lif->txqcqs[i], derr); + derr = ionic_qcq_disable(lif, lif->rxqcqs[i], derr); } return err; @@ -2896,6 +2735,9 @@ int ionic_lif_alloc(struct ionic *ionic) snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index); + mutex_init(&lif->queue_lock); + mutex_init(&lif->config_lock); + spin_lock_init(&lif->adminq_lock); spin_lock_init(&lif->deferred.lock); @@ -2909,7 +2751,7 @@ int ionic_lif_alloc(struct ionic *ionic) if (!lif->info) { dev_err(dev, "Failed to allocate lif info, aborting\n"); err = -ENOMEM; - goto err_out_free_netdev; + goto err_out_free_mutex; } ionic_debugfs_add_lif(lif); @@ -2944,6 +2786,9 @@ err_out_free_lif_info: dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa); lif->info = NULL; lif->info_pa = 0; +err_out_free_mutex: + mutex_destroy(&lif->config_lock); + mutex_destroy(&lif->queue_lock); err_out_free_netdev: free_netdev(lif->netdev); lif = NULL; @@ -2974,11 +2819,10 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif) netif_device_detach(lif->netdev); + mutex_lock(&lif->queue_lock); 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)) { @@ -2989,6 +2833,8 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif) ionic_reset(ionic); ionic_qcqs_free(lif); + mutex_unlock(&lif->queue_lock); + dev_info(ionic->dev, "FW Down: LIFs stopped\n"); } @@ -3012,9 +2858,12 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) err = ionic_port_init(ionic); if (err) goto err_out; + + mutex_lock(&lif->queue_lock); + err = ionic_qcqs_alloc(lif); if (err) - goto err_out; + goto err_unlock; err = ionic_lif_init(lif); if (err) @@ -3035,6 +2884,8 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) goto err_txrx_free; } + mutex_unlock(&lif->queue_lock); + clear_bit(IONIC_LIF_F_FW_RESET, lif->state); ionic_link_status_check_request(lif, CAN_SLEEP); netif_device_attach(lif->netdev); @@ -3051,6 +2902,8 @@ err_lifs_deinit: ionic_lif_deinit(lif); err_qcqs_free: ionic_qcqs_free(lif); +err_unlock: + mutex_unlock(&lif->queue_lock); err_out: dev_err(ionic->dev, "FW Up: LIFs restart failed - err %d\n", err); } @@ -3084,6 +2937,9 @@ void ionic_lif_free(struct ionic_lif *lif) kfree(lif->dbid_inuse); lif->dbid_inuse = NULL; + mutex_destroy(&lif->config_lock); + mutex_destroy(&lif->queue_lock); + /* free netdev & lif */ ionic_debugfs_del_lif(lif); free_netdev(lif->netdev); @@ -3106,8 +2962,6 @@ void ionic_lif_deinit(struct ionic_lif *lif) ionic_lif_qcq_deinit(lif, lif->notifyqcq); ionic_lif_qcq_deinit(lif, lif->adminqcq); - mutex_destroy(&lif->config_lock); - mutex_destroy(&lif->queue_lock); ionic_lif_reset(lif); } @@ -3273,8 +3127,6 @@ int ionic_lif_init(struct ionic_lif *lif) return err; lif->hw_index = le16_to_cpu(comp.hw_index); - mutex_init(&lif->queue_lock); - mutex_init(&lif->config_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); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index 4915184f3efb..9f7ab2f17f93 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -14,9 +14,6 @@ #define IONIC_ADMINQ_LENGTH 16 /* must be a power of two */ #define IONIC_NOTIFYQ_LENGTH 64 /* must be a power of two */ -#define IONIC_MAX_NUM_NAPI_CNTR (NAPI_POLL_WEIGHT + 1) -#define IONIC_MAX_NUM_SG_CNTR (IONIC_TX_MAX_SG_ELEMS + 1) - #define ADD_ADDR true #define DEL_ADDR false #define CAN_SLEEP true @@ -37,7 +34,6 @@ struct ionic_tx_stats { u64 clean; u64 linearize; u64 crc32_csum; - u64 sg_cntr[IONIC_MAX_NUM_SG_CNTR]; u64 dma_map_err; u64 hwstamp_valid; u64 hwstamp_invalid; @@ -48,7 +44,6 @@ struct ionic_rx_stats { u64 bytes; u64 csum_none; u64 csum_complete; - u64 buffers_posted; u64 dropped; u64 vlan_stripped; u64 csum_error; @@ -65,11 +60,6 @@ struct ionic_rx_stats { #define IONIC_QCQ_F_RX_STATS BIT(4) #define IONIC_QCQ_F_NOTIFYQ BIT(5) -struct ionic_napi_stats { - u64 poll_count; - u64 work_done_cntr[IONIC_MAX_NUM_NAPI_CNTR]; -}; - struct ionic_qcq { void *q_base; dma_addr_t q_base_pa; @@ -85,7 +75,6 @@ struct ionic_qcq { struct ionic_cq cq; struct ionic_intr_info intr; struct napi_struct napi; - struct ionic_napi_stats napi_stats; unsigned int flags; struct dentry *dentry; }; @@ -142,7 +131,6 @@ struct ionic_lif_sw_stats { enum ionic_lif_state_flags { IONIC_LIF_F_INITED, - IONIC_LIF_F_SW_DEBUG_STATS, IONIC_LIF_F_UP, IONIC_LIF_F_LINK_CHECK_REQUESTED, IONIC_LIF_F_FILTER_SYNC_NEEDED, @@ -201,11 +189,11 @@ struct ionic_lif { u16 rx_mode; u64 hw_features; bool registered; - bool mc_overflow; - bool uc_overflow; u16 lif_type; unsigned int nmcast; unsigned int nucast; + unsigned int nvlans; + unsigned int max_vlans; char name[IONIC_LIF_NAME_MAX_SZ]; union ionic_lif_identity *identity; @@ -350,37 +338,4 @@ int ionic_lif_rss_config(struct ionic_lif *lif, u16 types, void ionic_lif_rx_mode(struct ionic_lif *lif); int ionic_reconfigure_queues(struct ionic_lif *lif, struct ionic_queue_params *qparam); - -static inline void debug_stats_txq_post(struct ionic_queue *q, bool dbell) -{ - struct ionic_txq_desc *desc = &q->txq[q->head_idx]; - u8 num_sg_elems; - - q->dbell_count += dbell; - - num_sg_elems = ((le64_to_cpu(desc->cmd) >> IONIC_TXQ_DESC_NSGE_SHIFT) - & IONIC_TXQ_DESC_NSGE_MASK); - if (num_sg_elems > (IONIC_MAX_NUM_SG_CNTR - 1)) - num_sg_elems = IONIC_MAX_NUM_SG_CNTR - 1; - - q->lif->txqstats[q->index].sg_cntr[num_sg_elems]++; -} - -static inline void debug_stats_napi_poll(struct ionic_qcq *qcq, - unsigned int work_done) -{ - qcq->napi_stats.poll_count++; - - if (work_done > (IONIC_MAX_NUM_NAPI_CNTR - 1)) - work_done = IONIC_MAX_NUM_NAPI_CNTR - 1; - - qcq->napi_stats.work_done_cntr[work_done]++; -} - -#define DEBUG_STATS_CQE_CNT(cq) ((cq)->compl_count++) -#define DEBUG_STATS_RX_BUFF_CNT(q) ((q)->lif->rxqstats[q->index].buffers_posted++) -#define DEBUG_STATS_TXQ_POST(q, dbell) debug_stats_txq_post(q, dbell) -#define DEBUG_STATS_NAPI_POLL(qcq, work_done) \ - debug_stats_napi_poll(qcq, work_done) - #endif /* _IONIC_LIF_H_ */ diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index 6f07bf509efe..875f4ec42efe 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -7,6 +7,7 @@ #include <linux/netdevice.h> #include <linux/utsname.h> #include <generated/utsrelease.h> +#include <linux/ctype.h> #include "ionic.h" #include "ionic_bus.h" @@ -211,24 +212,28 @@ static void ionic_adminq_flush(struct ionic_lif *lif) spin_unlock_irqrestore(&lif->adminq_lock, irqflags); } +void ionic_adminq_netdev_err_print(struct ionic_lif *lif, u8 opcode, + u8 status, int err) +{ + netdev_err(lif->netdev, "%s (%d) failed: %s (%d)\n", + ionic_opcode_to_str(opcode), opcode, + ionic_error_to_str(status), err); +} + static int ionic_adminq_check_err(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, - bool timeout) + const bool timeout, + const bool do_msg) { - struct net_device *netdev = lif->netdev; - const char *opcode_str; - const char *status_str; int err = 0; if (ctx->comp.comp.status || timeout) { - opcode_str = ionic_opcode_to_str(ctx->cmd.cmd.opcode); - status_str = ionic_error_to_str(ctx->comp.comp.status); err = timeout ? -ETIMEDOUT : ionic_error_to_errno(ctx->comp.comp.status); - netdev_err(netdev, "%s (%d) failed: %s (%d)\n", - opcode_str, ctx->cmd.cmd.opcode, - timeout ? "TIMEOUT" : status_str, err); + if (do_msg) + ionic_adminq_netdev_err_print(lif, ctx->cmd.cmd.opcode, + ctx->comp.comp.status, err); if (timeout) ionic_adminq_flush(lif); @@ -297,24 +302,52 @@ err_out: return err; } -int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, int err) +int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, + const int err, const bool do_msg) { struct net_device *netdev = lif->netdev; + unsigned long time_limit; + unsigned long time_start; + unsigned long time_done; unsigned long remaining; const char *name; + name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); + if (err) { - if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { - name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); + if (do_msg && !test_bit(IONIC_LIF_F_FW_RESET, lif->state)) netdev_err(netdev, "Posting of %s (%d) failed: %d\n", name, ctx->cmd.cmd.opcode, err); - } return err; } - remaining = wait_for_completion_timeout(&ctx->work, - HZ * (ulong)DEVCMD_TIMEOUT); - return ionic_adminq_check_err(lif, ctx, (remaining == 0)); + time_start = jiffies; + time_limit = time_start + HZ * (ulong)DEVCMD_TIMEOUT; + do { + remaining = wait_for_completion_timeout(&ctx->work, + IONIC_ADMINQ_TIME_SLICE); + + /* check for done */ + if (remaining) + break; + + /* interrupt the wait if FW stopped */ + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { + if (do_msg) + netdev_err(netdev, "%s (%d) interrupted, FW in reset\n", + name, ctx->cmd.cmd.opcode); + return -ENXIO; + } + + } while (time_before(jiffies, time_limit)); + time_done = jiffies; + + dev_dbg(lif->ionic->dev, "%s: elapsed %d msecs\n", + __func__, jiffies_to_msecs(time_done - time_start)); + + return ionic_adminq_check_err(lif, ctx, + time_after_eq(time_done, time_limit), + do_msg); } int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) @@ -323,7 +356,16 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) err = ionic_adminq_post(lif, ctx); - return ionic_adminq_wait(lif, ctx, err); + return ionic_adminq_wait(lif, ctx, err, true); +} + +int ionic_adminq_post_wait_nomsg(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) +{ + int err; + + err = ionic_adminq_post(lif, ctx); + + return ionic_adminq_wait(lif, ctx, err, false); } static void ionic_dev_cmd_clean(struct ionic *ionic) @@ -450,13 +492,23 @@ int ionic_identify(struct ionic *ionic) } mutex_unlock(&ionic->dev_cmd_lock); - dev_info(ionic->dev, "FW: %s\n", idev->dev_info.fw_version); - if (err) { - dev_err(ionic->dev, "Cannot identify ionic: %dn", err); + dev_err(ionic->dev, "Cannot identify ionic: %d\n", err); goto err_out; } + if (isprint(idev->dev_info.fw_version[0]) && + isascii(idev->dev_info.fw_version[0])) + dev_info(ionic->dev, "FW: %.*s\n", + (int)(sizeof(idev->dev_info.fw_version) - 1), + idev->dev_info.fw_version); + else + dev_info(ionic->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n", + (u8)idev->dev_info.fw_version[0], + (u8)idev->dev_info.fw_version[1], + (u8)idev->dev_info.fw_version[2], + (u8)idev->dev_info.fw_version[3]); + err = ionic_lif_identify(ionic, IONIC_LIF_TYPE_CLASSIC, &ionic->ident.lif); if (err) { diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c index eed2db69d708..887046838b3b 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c @@ -348,7 +348,7 @@ static int ionic_phc_adjfine(struct ptp_clock_info *info, long scaled_ppm) spin_unlock_irqrestore(&phc->lock, irqflags); - return ionic_adminq_wait(phc->lif, &ctx, err); + return ionic_adminq_wait(phc->lif, &ctx, err, true); } static int ionic_phc_adjtime(struct ptp_clock_info *info, s64 delta) @@ -373,7 +373,7 @@ static int ionic_phc_adjtime(struct ptp_clock_info *info, s64 delta) spin_unlock_irqrestore(&phc->lock, irqflags); - return ionic_adminq_wait(phc->lif, &ctx, err); + return ionic_adminq_wait(phc->lif, &ctx, err, true); } static int ionic_phc_settime64(struct ptp_clock_info *info, @@ -402,7 +402,7 @@ static int ionic_phc_settime64(struct ptp_clock_info *info, spin_unlock_irqrestore(&phc->lock, irqflags); - return ionic_adminq_wait(phc->lif, &ctx, err); + return ionic_adminq_wait(phc->lif, &ctx, err, true); } static int ionic_phc_gettimex64(struct ptp_clock_info *info, @@ -459,7 +459,7 @@ static long ionic_phc_aux_work(struct ptp_clock_info *info) spin_unlock_irqrestore(&phc->lock, irqflags); - ionic_adminq_wait(phc->lif, &ctx, err); + ionic_adminq_wait(phc->lif, &ctx, err, true); return phc->aux_work_delay; } diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c index 69728f9013cb..f6e785f949f9 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c @@ -239,6 +239,21 @@ struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif) return NULL; } +static struct ionic_rx_filter *ionic_rx_filter_find(struct ionic_lif *lif, + struct ionic_rx_filter_add_cmd *ac) +{ + switch (le16_to_cpu(ac->match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + return ionic_rx_filter_by_vlan(lif, le16_to_cpu(ac->vlan.vlan)); + case IONIC_RX_FILTER_MATCH_MAC: + return ionic_rx_filter_by_addr(lif, ac->mac.addr); + default: + netdev_err(lif->netdev, "unsupported filter match %d", + le16_to_cpu(ac->match)); + return NULL; + } +} + int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode) { struct ionic_rx_filter *f; @@ -286,6 +301,228 @@ int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode) return 0; } +static int ionic_lif_filter_add(struct ionic_lif *lif, + struct ionic_rx_filter_add_cmd *ac) +{ + struct ionic_admin_ctx ctx = { + .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), + }; + struct ionic_rx_filter *f; + int nfilters; + int err = 0; + + ctx.cmd.rx_filter_add = *ac; + ctx.cmd.rx_filter_add.opcode = IONIC_CMD_RX_FILTER_ADD, + ctx.cmd.rx_filter_add.lif_index = cpu_to_le16(lif->index), + + spin_lock_bh(&lif->rx_filters.lock); + f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); + if (f) { + /* don't bother if we already have it and it is sync'd */ + if (f->state == IONIC_FILTER_STATE_SYNCED) { + spin_unlock_bh(&lif->rx_filters.lock); + return 0; + } + + /* mark preemptively as sync'd to block any parallel attempts */ + f->state = IONIC_FILTER_STATE_SYNCED; + } else { + /* save as SYNCED to catch any DEL requests while processing */ + err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, + IONIC_FILTER_STATE_SYNCED); + } + spin_unlock_bh(&lif->rx_filters.lock); + if (err) + return err; + + /* Don't bother with the write to FW if we know there's no room, + * we can try again on the next sync attempt. + * Since the FW doesn't have a way to tell us the vlan limit, + * we start max_vlans at 0 until we hit the ENOSPC error. + */ + switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + netdev_dbg(lif->netdev, "%s: rx_filter add VLAN %d\n", + __func__, ctx.cmd.rx_filter_add.vlan.vlan); + if (lif->max_vlans && lif->nvlans >= lif->max_vlans) + err = -ENOSPC; + break; + case IONIC_RX_FILTER_MATCH_MAC: + netdev_dbg(lif->netdev, "%s: rx_filter add ADDR %pM\n", + __func__, ctx.cmd.rx_filter_add.mac.addr); + nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters); + if ((lif->nucast + lif->nmcast) >= nfilters) + err = -ENOSPC; + break; + } + + if (err != -ENOSPC) + err = ionic_adminq_post_wait_nomsg(lif, &ctx); + + spin_lock_bh(&lif->rx_filters.lock); + + if (err && err != -EEXIST) { + /* set the state back to NEW so we can try again later */ + f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); + if (f && f->state == IONIC_FILTER_STATE_SYNCED) { + f->state = IONIC_FILTER_STATE_NEW; + + /* If -ENOSPC we won't waste time trying to sync again + * until there is a delete that might make room + */ + if (err != -ENOSPC) + set_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state); + } + + spin_unlock_bh(&lif->rx_filters.lock); + + if (err == -ENOSPC) { + if (le16_to_cpu(ctx.cmd.rx_filter_add.match) == IONIC_RX_FILTER_MATCH_VLAN) + lif->max_vlans = lif->nvlans; + return 0; + } + + ionic_adminq_netdev_err_print(lif, ctx.cmd.cmd.opcode, + ctx.comp.comp.status, err); + switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + netdev_info(lif->netdev, "rx_filter add failed: VLAN %d\n", + ctx.cmd.rx_filter_add.vlan.vlan); + break; + case IONIC_RX_FILTER_MATCH_MAC: + netdev_info(lif->netdev, "rx_filter add failed: ADDR %pM\n", + ctx.cmd.rx_filter_add.mac.addr); + break; + } + + return err; + } + + switch (le16_to_cpu(ctx.cmd.rx_filter_add.match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + lif->nvlans++; + break; + case IONIC_RX_FILTER_MATCH_MAC: + if (is_multicast_ether_addr(ctx.cmd.rx_filter_add.mac.addr)) + lif->nmcast++; + else + lif->nucast++; + break; + } + + f = ionic_rx_filter_find(lif, &ctx.cmd.rx_filter_add); + if (f && f->state == IONIC_FILTER_STATE_OLD) { + /* Someone requested a delete while we were adding + * so update the filter info with the results from the add + * and the data will be there for the delete on the next + * sync cycle. + */ + err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, + IONIC_FILTER_STATE_OLD); + } else { + err = ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx, + IONIC_FILTER_STATE_SYNCED); + } + + spin_unlock_bh(&lif->rx_filters.lock); + + return err; +} + +int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) +{ + struct ionic_rx_filter_add_cmd ac = { + .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_MAC), + }; + + memcpy(&ac.mac.addr, addr, ETH_ALEN); + + return ionic_lif_filter_add(lif, &ac); +} + +int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid) +{ + struct ionic_rx_filter_add_cmd ac = { + .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN), + .vlan.vlan = cpu_to_le16(vid), + }; + + return ionic_lif_filter_add(lif, &ac); +} + +static int ionic_lif_filter_del(struct ionic_lif *lif, + struct ionic_rx_filter_add_cmd *ac) +{ + struct ionic_admin_ctx ctx = { + .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), + .cmd.rx_filter_del = { + .opcode = IONIC_CMD_RX_FILTER_DEL, + .lif_index = cpu_to_le16(lif->index), + }, + }; + struct ionic_rx_filter *f; + int state; + int err; + + spin_lock_bh(&lif->rx_filters.lock); + f = ionic_rx_filter_find(lif, ac); + if (!f) { + spin_unlock_bh(&lif->rx_filters.lock); + return -ENOENT; + } + + switch (le16_to_cpu(ac->match)) { + case IONIC_RX_FILTER_MATCH_VLAN: + netdev_dbg(lif->netdev, "%s: rx_filter del VLAN %d id %d\n", + __func__, ac->vlan.vlan, f->filter_id); + lif->nvlans--; + break; + case IONIC_RX_FILTER_MATCH_MAC: + netdev_dbg(lif->netdev, "%s: rx_filter del ADDR %pM id %d\n", + __func__, ac->mac.addr, f->filter_id); + if (is_multicast_ether_addr(ac->mac.addr) && lif->nmcast) + lif->nmcast--; + else if (!is_multicast_ether_addr(ac->mac.addr) && lif->nucast) + lif->nucast--; + break; + } + + state = f->state; + 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); + + if (state != IONIC_FILTER_STATE_NEW) { + err = ionic_adminq_post_wait(lif, &ctx); + if (err && err != -EEXIST) + return err; + } + + return 0; +} + +int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) +{ + struct ionic_rx_filter_add_cmd ac = { + .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_MAC), + }; + + memcpy(&ac.mac.addr, addr, ETH_ALEN); + + return ionic_lif_filter_del(lif, &ac); +} + +int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid) +{ + struct ionic_rx_filter_add_cmd ac = { + .match = cpu_to_le16(IONIC_RX_FILTER_MATCH_VLAN), + .vlan.vlan = cpu_to_le16(vid), + }; + + return ionic_lif_filter_del(lif, &ac); +} + struct sync_item { struct list_head list; struct ionic_rx_filter f; @@ -340,14 +577,14 @@ loop_out: * they can clear room for some new filters */ list_for_each_entry_safe(sync_item, spos, &sync_del_list, list) { - (void)ionic_lif_addr_del(lif, sync_item->f.cmd.mac.addr); + (void)ionic_lif_filter_del(lif, &sync_item->f.cmd); list_del(&sync_item->list); devm_kfree(dev, sync_item); } list_for_each_entry_safe(sync_item, spos, &sync_add_list, list) { - (void)ionic_lif_addr_add(lif, sync_item->f.cmd.mac.addr); + (void)ionic_lif_filter_add(lif, &sync_item->f.cmd); list_del(&sync_item->list); devm_kfree(dev, sync_item); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h index a66e35f0833b..87b2666f248b 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.h @@ -44,5 +44,7 @@ struct ionic_rx_filter *ionic_rx_filter_rxsteer(struct ionic_lif *lif); void ionic_rx_filter_sync(struct ionic_lif *lif); int ionic_lif_list_addr(struct ionic_lif *lif, const u8 *addr, bool mode); int ionic_rx_filters_need_sync(struct ionic_lif *lif); +int ionic_lif_vlan_add(struct ionic_lif *lif, const u16 vid); +int ionic_lif_vlan_del(struct ionic_lif *lif, const u16 vid); #endif /* _IONIC_RX_FILTER_H_ */ diff --git a/drivers/net/ethernet/pensando/ionic/ionic_stats.c b/drivers/net/ethernet/pensando/ionic/ionic_stats.c index c14de5fcedea..fd6806b4a1b9 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_stats.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_stats.c @@ -151,33 +151,11 @@ static const struct ionic_stat_desc ionic_rx_stats_desc[] = { IONIC_RX_STAT_DESC(vlan_stripped), }; -static const struct ionic_stat_desc ionic_txq_stats_desc[] = { - IONIC_TX_Q_STAT_DESC(stop), - IONIC_TX_Q_STAT_DESC(wake), - IONIC_TX_Q_STAT_DESC(drop), - IONIC_TX_Q_STAT_DESC(dbell_count), -}; - -static const struct ionic_stat_desc ionic_dbg_cq_stats_desc[] = { - IONIC_CQ_STAT_DESC(compl_count), -}; - -static const struct ionic_stat_desc ionic_dbg_intr_stats_desc[] = { - IONIC_INTR_STAT_DESC(rearm_count), -}; - -static const struct ionic_stat_desc ionic_dbg_napi_stats_desc[] = { - IONIC_NAPI_STAT_DESC(poll_count), -}; #define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc) #define IONIC_NUM_PORT_STATS ARRAY_SIZE(ionic_port_stats_desc) #define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc) #define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc) -#define IONIC_NUM_TX_Q_STATS ARRAY_SIZE(ionic_txq_stats_desc) -#define IONIC_NUM_DBG_CQ_STATS ARRAY_SIZE(ionic_dbg_cq_stats_desc) -#define IONIC_NUM_DBG_INTR_STATS ARRAY_SIZE(ionic_dbg_intr_stats_desc) -#define IONIC_NUM_DBG_NAPI_STATS ARRAY_SIZE(ionic_dbg_napi_stats_desc) #define MAX_Q(lif) ((lif)->netdev->real_num_tx_queues) @@ -253,21 +231,6 @@ static u64 ionic_sw_stats_get_count(struct ionic_lif *lif) total += tx_queues * IONIC_NUM_TX_STATS; total += rx_queues * IONIC_NUM_RX_STATS; - if (test_bit(IONIC_LIF_F_UP, lif->state) && - test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) { - /* tx debug stats */ - total += tx_queues * (IONIC_NUM_DBG_CQ_STATS + - IONIC_NUM_TX_Q_STATS + - IONIC_NUM_DBG_INTR_STATS + - IONIC_MAX_NUM_SG_CNTR); - - /* rx debug stats */ - total += rx_queues * (IONIC_NUM_DBG_CQ_STATS + - IONIC_NUM_DBG_INTR_STATS + - IONIC_NUM_DBG_NAPI_STATS + - IONIC_MAX_NUM_NAPI_CNTR); - } - return total; } @@ -279,22 +242,6 @@ static void ionic_sw_stats_get_tx_strings(struct ionic_lif *lif, u8 **buf, for (i = 0; i < IONIC_NUM_TX_STATS; i++) ethtool_sprintf(buf, "tx_%d_%s", q_num, ionic_tx_stats_desc[i].name); - - if (!test_bit(IONIC_LIF_F_UP, lif->state) || - !test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) - return; - - for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) - ethtool_sprintf(buf, "txq_%d_%s", q_num, - ionic_txq_stats_desc[i].name); - for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) - ethtool_sprintf(buf, "txq_%d_cq_%s", q_num, - ionic_dbg_cq_stats_desc[i].name); - for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) - ethtool_sprintf(buf, "txq_%d_intr_%s", q_num, - ionic_dbg_intr_stats_desc[i].name); - for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) - ethtool_sprintf(buf, "txq_%d_sg_cntr_%d", q_num, i); } static void ionic_sw_stats_get_rx_strings(struct ionic_lif *lif, u8 **buf, @@ -305,22 +252,6 @@ static void ionic_sw_stats_get_rx_strings(struct ionic_lif *lif, u8 **buf, for (i = 0; i < IONIC_NUM_RX_STATS; i++) ethtool_sprintf(buf, "rx_%d_%s", q_num, ionic_rx_stats_desc[i].name); - - if (!test_bit(IONIC_LIF_F_UP, lif->state) || - !test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) - return; - - for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) - ethtool_sprintf(buf, "rxq_%d_cq_%s", q_num, - ionic_dbg_cq_stats_desc[i].name); - for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) - ethtool_sprintf(buf, "rxq_%d_intr_%s", q_num, - ionic_dbg_intr_stats_desc[i].name); - for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) - ethtool_sprintf(buf, "rxq_%d_napi_%s", q_num, - ionic_dbg_napi_stats_desc[i].name); - for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) - ethtool_sprintf(buf, "rxq_%d_napi_work_done_%d", q_num, i); } static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) @@ -350,7 +281,6 @@ static void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf, int q_num) { struct ionic_tx_stats *txstats; - struct ionic_qcq *txqcq; int i; txstats = &lif->txqstats[q_num]; @@ -359,38 +289,12 @@ static void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf, **buf = IONIC_READ_STAT64(txstats, &ionic_tx_stats_desc[i]); (*buf)++; } - - if (!test_bit(IONIC_LIF_F_UP, lif->state) || - !test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) - return; - - txqcq = lif->txqcqs[q_num]; - for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { - **buf = IONIC_READ_STAT64(&txqcq->q, - &ionic_txq_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { - **buf = IONIC_READ_STAT64(&txqcq->cq, - &ionic_dbg_cq_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { - **buf = IONIC_READ_STAT64(&txqcq->intr, - &ionic_dbg_intr_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { - **buf = txstats->sg_cntr[i]; - (*buf)++; - } } static void ionic_sw_stats_get_rxq_values(struct ionic_lif *lif, u64 **buf, int q_num) { struct ionic_rx_stats *rxstats; - struct ionic_qcq *rxqcq; int i; rxstats = &lif->rxqstats[q_num]; @@ -399,31 +303,6 @@ static void ionic_sw_stats_get_rxq_values(struct ionic_lif *lif, u64 **buf, **buf = IONIC_READ_STAT64(rxstats, &ionic_rx_stats_desc[i]); (*buf)++; } - - if (!test_bit(IONIC_LIF_F_UP, lif->state) || - !test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) - return; - - rxqcq = lif->rxqcqs[q_num]; - for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { - **buf = IONIC_READ_STAT64(&rxqcq->cq, - &ionic_dbg_cq_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { - **buf = IONIC_READ_STAT64(&rxqcq->intr, - &ionic_dbg_intr_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { - **buf = IONIC_READ_STAT64(&rxqcq->napi_stats, - &ionic_dbg_napi_stats_desc[i]); - (*buf)++; - } - for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { - **buf = rxqcq->napi_stats.work_done_cntr[i]; - (*buf)++; - } } static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c index 37c39581b659..94384f5d2a22 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c @@ -14,8 +14,6 @@ static inline void ionic_txq_post(struct ionic_queue *q, bool ring_dbell, ionic_desc_cb cb_func, void *cb_arg) { - DEBUG_STATS_TXQ_POST(q, ring_dbell); - ionic_q_post(q, ring_dbell, cb_func, cb_arg); } @@ -23,8 +21,6 @@ static inline void ionic_rxq_post(struct ionic_queue *q, bool ring_dbell, ionic_desc_cb cb_func, void *cb_arg) { ionic_q_post(q, ring_dbell, cb_func, cb_arg); - - DEBUG_STATS_RX_BUFF_CNT(q); } static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q) @@ -507,8 +503,6 @@ int ionic_tx_napi(struct napi_struct *napi, int budget) work_done, flags); } - DEBUG_STATS_NAPI_POLL(qcq, work_done); - return work_done; } @@ -546,8 +540,6 @@ int ionic_rx_napi(struct napi_struct *napi, int budget) work_done, flags); } - DEBUG_STATS_NAPI_POLL(qcq, work_done); - return work_done; } @@ -591,9 +583,6 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) tx_work_done + rx_work_done, flags); } - DEBUG_STATS_NAPI_POLL(qcq, rx_work_done); - DEBUG_STATS_NAPI_POLL(qcq, tx_work_done); - return rx_work_done; } @@ -735,7 +724,6 @@ static void ionic_tx_clean(struct ionic_queue *q, } else if (unlikely(__netif_subqueue_stopped(q->lif->netdev, qi))) { netif_wake_subqueue(q->lif->netdev, qi); - q->wake++; } desc_info->bytes = skb->len; @@ -1174,7 +1162,6 @@ static int ionic_maybe_stop_tx(struct ionic_queue *q, int ndescs) if (unlikely(!ionic_q_has_space(q, ndescs))) { netif_stop_subqueue(q->lif->netdev, q->index); - q->stop++; stopped = 1; /* Might race with ionic_tx_clean, check again */ @@ -1269,7 +1256,6 @@ netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; err_out_drop: - q->stop++; q->drop++; dev_kfree_skb(skb); return NETDEV_TX_OK; |