diff options
Diffstat (limited to 'drivers/net/ethernet/pensando/ionic/ionic_lif.c')
| -rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_lif.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 025ad6a6fce4..966a81006528 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -1315,6 +1315,65 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, return ionic_adminq_post_wait(lif, &ctx); } +int ionic_lif_rss_config(struct ionic_lif *lif, const u16 types, + const u8 *key, const u32 *indir) +{ + struct ionic_admin_ctx ctx = { + .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), + .cmd.lif_setattr = { + .opcode = IONIC_CMD_LIF_SETATTR, + .attr = IONIC_LIF_ATTR_RSS, + .rss.types = cpu_to_le16(types), + .rss.addr = cpu_to_le64(lif->rss_ind_tbl_pa), + }, + }; + unsigned int i, tbl_sz; + + lif->rss_types = types; + + if (key) + memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE); + + if (indir) { + tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz); + for (i = 0; i < tbl_sz; i++) + lif->rss_ind_tbl[i] = indir[i]; + } + + memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key, + IONIC_RSS_HASH_KEY_SIZE); + + return ionic_adminq_post_wait(lif, &ctx); +} + +static int ionic_lif_rss_init(struct ionic_lif *lif) +{ + u8 rss_key[IONIC_RSS_HASH_KEY_SIZE]; + unsigned int tbl_sz; + unsigned int i; + + netdev_rss_key_fill(rss_key, IONIC_RSS_HASH_KEY_SIZE); + + lif->rss_types = IONIC_RSS_TYPE_IPV4 | + IONIC_RSS_TYPE_IPV4_TCP | + IONIC_RSS_TYPE_IPV4_UDP | + IONIC_RSS_TYPE_IPV6 | + IONIC_RSS_TYPE_IPV6_TCP | + IONIC_RSS_TYPE_IPV6_UDP; + + /* Fill indirection table with 'default' values */ + tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz); + for (i = 0; i < tbl_sz; i++) + lif->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, lif->nxqs); + + return ionic_lif_rss_config(lif, lif->rss_types, rss_key, NULL); +} + +static int ionic_lif_rss_deinit(struct ionic_lif *lif) +{ + return ionic_lif_rss_config(lif, 0x0, NULL, NULL); +} + static void ionic_txrx_disable(struct ionic_lif *lif) { unsigned int i; @@ -1413,6 +1472,9 @@ static int ionic_txrx_init(struct ionic_lif *lif) } } + if (lif->netdev->features & NETIF_F_RXHASH) + ionic_lif_rss_init(lif); + ionic_set_rx_mode(lif->netdev); return 0; @@ -1558,6 +1620,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index struct device *dev = ionic->dev; struct net_device *netdev; struct ionic_lif *lif; + int tbl_sz; int err; netdev = alloc_etherdev_mqs(sizeof(*lif), @@ -1610,10 +1673,24 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index if (err) goto err_out_free_lif_info; + /* allocate rss indirection table */ + tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz); + lif->rss_ind_tbl_sz = sizeof(*lif->rss_ind_tbl) * tbl_sz; + lif->rss_ind_tbl = dma_alloc_coherent(dev, lif->rss_ind_tbl_sz, + &lif->rss_ind_tbl_pa, + GFP_KERNEL); + + if (!lif->rss_ind_tbl) { + dev_err(dev, "Failed to allocate rss indirection table, aborting\n"); + goto err_out_free_qcqs; + } + list_add_tail(&lif->list, &ionic->lifs); return lif; +err_out_free_qcqs: + ionic_qcqs_free(lif); err_out_free_lif_info: dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa); lif->info = NULL; @@ -1652,6 +1729,12 @@ static void ionic_lif_free(struct ionic_lif *lif) { struct device *dev = lif->ionic->dev; + /* free rss indirection table */ + dma_free_coherent(dev, lif->rss_ind_tbl_sz, lif->rss_ind_tbl, + lif->rss_ind_tbl_pa); + lif->rss_ind_tbl = NULL; + lif->rss_ind_tbl_pa = 0; + /* free queues */ ionic_qcqs_free(lif); ionic_lif_reset(lif); @@ -1693,6 +1776,7 @@ static void ionic_lif_deinit(struct ionic_lif *lif) clear_bit(IONIC_LIF_INITED, lif->state); ionic_rx_filters_deinit(lif); + ionic_lif_rss_deinit(lif); napi_disable(&lif->adminqcq->napi); ionic_lif_qcq_deinit(lif, lif->notifyqcq); |
