Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'eth-bnxt-use-the-new-rss-api'

Jakub Kicinski says:

====================
eth: bnxt: use the new RSS API

Convert bnxt from using the set_rxfh API to separate create/modify/remove
callbacks.

Two small extensions to the core APIs are necessary:
- the ability to discard contexts if for some catastrophic reasons
device can no longer provide them;
- the ability to reserve space in the context for RSS table growth.

The driver is adjusted to store indirection tables on u32 to make
it easier to use core structs directly.

With that out of the way the conversion is fairly straightforward.

Since the opposition to discarding contexts was relatively mild
and its what bnxt does already, I'm sticking to that. We may very
well need to revisit that at a later time.

v1: https://lore.kernel.org/all/20240702234757.4188344-1-kuba@kernel.org/
====================

Link: https://patch.msgid.link/20240711220713.283778-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+194 -194
+42 -84
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 5970 5970 struct hwrm_cfa_ntuple_filter_alloc_input *req, 5971 5971 struct bnxt_ntuple_filter *fltr) 5972 5972 { 5973 - struct bnxt_rss_ctx *rss_ctx, *tmp; 5974 5973 u16 rxq = fltr->base.rxq; 5975 5974 5976 5975 if (fltr->base.flags & BNXT_ACT_RSS_CTX) { 5977 - list_for_each_entry_safe(rss_ctx, tmp, &bp->rss_ctx_list, list) { 5978 - if (rss_ctx->index == fltr->base.fw_vnic_id) { 5979 - struct bnxt_vnic_info *vnic = &rss_ctx->vnic; 5976 + struct ethtool_rxfh_context *ctx; 5977 + struct bnxt_rss_ctx *rss_ctx; 5978 + struct bnxt_vnic_info *vnic; 5980 5979 5981 - req->dst_id = cpu_to_le16(vnic->fw_vnic_id); 5982 - break; 5983 - } 5980 + ctx = xa_load(&bp->dev->ethtool->rss_ctx, 5981 + fltr->base.fw_vnic_id); 5982 + if (ctx) { 5983 + rss_ctx = ethtool_rxfh_context_priv(ctx); 5984 + vnic = &rss_ctx->vnic; 5985 + 5986 + req->dst_id = cpu_to_le16(vnic->fw_vnic_id); 5984 5987 } 5985 5988 return; 5986 5989 } ··· 6222 6219 return bnxt_cp_ring_from_grp(bp, &txr->tx_ring_struct); 6223 6220 } 6224 6221 6225 - int bnxt_alloc_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx) 6222 + static int bnxt_alloc_rss_indir_tbl(struct bnxt *bp) 6226 6223 { 6227 6224 int entries; 6228 - u16 *tbl; 6229 6225 6230 6226 if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) 6231 6227 entries = BNXT_MAX_RSS_TABLE_ENTRIES_P5; ··· 6232 6230 entries = HW_HASH_INDEX_SIZE; 6233 6231 6234 6232 bp->rss_indir_tbl_entries = entries; 6235 - tbl = kmalloc_array(entries, sizeof(*bp->rss_indir_tbl), GFP_KERNEL); 6236 - if (!tbl) 6233 + bp->rss_indir_tbl = 6234 + kmalloc_array(entries, sizeof(*bp->rss_indir_tbl), GFP_KERNEL); 6235 + if (!bp->rss_indir_tbl) 6237 6236 return -ENOMEM; 6238 - 6239 - if (rss_ctx) 6240 - rss_ctx->rss_indir_tbl = tbl; 6241 - else 6242 - bp->rss_indir_tbl = tbl; 6243 6237 6244 6238 return 0; 6245 6239 } 6246 6240 6247 - void bnxt_set_dflt_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx) 6241 + void bnxt_set_dflt_rss_indir_tbl(struct bnxt *bp, 6242 + struct ethtool_rxfh_context *rss_ctx) 6248 6243 { 6249 6244 u16 max_rings, max_entries, pad, i; 6250 - u16 *rss_indir_tbl; 6245 + u32 *rss_indir_tbl; 6251 6246 6252 6247 if (!bp->rx_nr_rings) 6253 6248 return; ··· 6256 6257 6257 6258 max_entries = bnxt_get_rxfh_indir_size(bp->dev); 6258 6259 if (rss_ctx) 6259 - rss_indir_tbl = &rss_ctx->rss_indir_tbl[0]; 6260 + rss_indir_tbl = ethtool_rxfh_context_indir(rss_ctx); 6260 6261 else 6261 6262 rss_indir_tbl = &bp->rss_indir_tbl[0]; 6262 6263 ··· 6265 6266 6266 6267 pad = bp->rss_indir_tbl_entries - max_entries; 6267 6268 if (pad) 6268 - memset(&rss_indir_tbl[i], 0, pad * sizeof(u16)); 6269 + memset(&rss_indir_tbl[i], 0, pad * sizeof(*rss_indir_tbl)); 6269 6270 } 6270 6271 6271 6272 static u16 bnxt_get_max_rss_ring(struct bnxt *bp) 6272 6273 { 6273 - u16 i, tbl_size, max_ring = 0; 6274 + u32 i, tbl_size, max_ring = 0; 6274 6275 6275 6276 if (!bp->rss_indir_tbl) 6276 6277 return 0; ··· 6278 6279 tbl_size = bnxt_get_rxfh_indir_size(bp->dev); 6279 6280 for (i = 0; i < tbl_size; i++) 6280 6281 max_ring = max(max_ring, bp->rss_indir_tbl[i]); 6281 - return max_ring; 6282 - } 6283 - 6284 - u16 bnxt_get_max_rss_ctx_ring(struct bnxt *bp) 6285 - { 6286 - u16 i, tbl_size, max_ring = 0; 6287 - struct bnxt_rss_ctx *rss_ctx; 6288 - 6289 - tbl_size = bnxt_get_rxfh_indir_size(bp->dev); 6290 - 6291 - list_for_each_entry(rss_ctx, &bp->rss_ctx_list, list) { 6292 - for (i = 0; i < tbl_size; i++) 6293 - max_ring = max(max_ring, rss_ctx->rss_indir_tbl[i]); 6294 - } 6295 - 6296 6282 return max_ring; 6297 6283 } 6298 6284 ··· 6322 6338 if (vnic->flags & BNXT_VNIC_NTUPLE_FLAG) 6323 6339 j = ethtool_rxfh_indir_default(i, bp->rx_nr_rings); 6324 6340 else if (vnic->flags & BNXT_VNIC_RSSCTX_FLAG) 6325 - j = vnic->rss_ctx->rss_indir_tbl[i]; 6341 + j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i]; 6326 6342 else 6327 6343 j = bp->rss_indir_tbl[i]; 6328 6344 rxr = &bp->rx_ring[j]; ··· 10194 10210 struct bnxt_ntuple_filter *ntp_fltr; 10195 10211 int i; 10196 10212 10197 - bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic); 10198 - for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) { 10199 - if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID) 10200 - bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i); 10213 + if (netif_running(bp->dev)) { 10214 + bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic); 10215 + for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) { 10216 + if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID) 10217 + bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i); 10218 + } 10201 10219 } 10202 10220 if (!all) 10203 10221 return; ··· 10220 10234 dma_free_coherent(&bp->pdev->dev, vnic->rss_table_size, 10221 10235 vnic->rss_table, 10222 10236 vnic->rss_table_dma_addr); 10223 - kfree(rss_ctx->rss_indir_tbl); 10224 - list_del(&rss_ctx->list); 10225 10237 bp->num_rss_ctx--; 10226 - clear_bit(rss_ctx->index, bp->rss_ctx_bmap); 10227 - kfree(rss_ctx); 10228 10238 } 10229 10239 10230 10240 static void bnxt_hwrm_realloc_rss_ctx_vnic(struct bnxt *bp) 10231 10241 { 10232 10242 bool set_tpa = !!(bp->flags & BNXT_FLAG_TPA); 10233 - struct bnxt_rss_ctx *rss_ctx, *tmp; 10243 + struct ethtool_rxfh_context *ctx; 10244 + unsigned long context; 10234 10245 10235 - list_for_each_entry_safe(rss_ctx, tmp, &bp->rss_ctx_list, list) { 10246 + xa_for_each(&bp->dev->ethtool->rss_ctx, context, ctx) { 10247 + struct bnxt_rss_ctx *rss_ctx = ethtool_rxfh_context_priv(ctx); 10236 10248 struct bnxt_vnic_info *vnic = &rss_ctx->vnic; 10237 10249 10238 10250 if (bnxt_hwrm_vnic_alloc(bp, vnic, 0, bp->rx_nr_rings) || ··· 10239 10255 netdev_err(bp->dev, "Failed to restore RSS ctx %d\n", 10240 10256 rss_ctx->index); 10241 10257 bnxt_del_one_rss_ctx(bp, rss_ctx, true); 10258 + ethtool_rxfh_context_lost(bp->dev, rss_ctx->index); 10242 10259 } 10243 10260 } 10244 10261 } 10245 10262 10246 - struct bnxt_rss_ctx *bnxt_alloc_rss_ctx(struct bnxt *bp) 10263 + void bnxt_clear_rss_ctxs(struct bnxt *bp) 10247 10264 { 10248 - struct bnxt_rss_ctx *rss_ctx = NULL; 10265 + struct ethtool_rxfh_context *ctx; 10266 + unsigned long context; 10249 10267 10250 - rss_ctx = kzalloc(sizeof(*rss_ctx), GFP_KERNEL); 10251 - if (rss_ctx) { 10252 - rss_ctx->vnic.rss_ctx = rss_ctx; 10253 - list_add_tail(&rss_ctx->list, &bp->rss_ctx_list); 10254 - bp->num_rss_ctx++; 10255 - } 10256 - return rss_ctx; 10257 - } 10268 + xa_for_each(&bp->dev->ethtool->rss_ctx, context, ctx) { 10269 + struct bnxt_rss_ctx *rss_ctx = ethtool_rxfh_context_priv(ctx); 10258 10270 10259 - void bnxt_clear_rss_ctxs(struct bnxt *bp, bool all) 10260 - { 10261 - struct bnxt_rss_ctx *rss_ctx, *tmp; 10262 - 10263 - list_for_each_entry_safe(rss_ctx, tmp, &bp->rss_ctx_list, list) 10264 - bnxt_del_one_rss_ctx(bp, rss_ctx, all); 10265 - 10266 - if (all) 10267 - bitmap_free(bp->rss_ctx_bmap); 10268 - } 10269 - 10270 - static void bnxt_init_multi_rss_ctx(struct bnxt *bp) 10271 - { 10272 - bp->rss_ctx_bmap = bitmap_zalloc(BNXT_RSS_CTX_BMAP_LEN, GFP_KERNEL); 10273 - if (bp->rss_ctx_bmap) { 10274 - /* burn index 0 since we cannot have context 0 */ 10275 - __set_bit(0, bp->rss_ctx_bmap); 10276 - INIT_LIST_HEAD(&bp->rss_ctx_list); 10277 - bp->rss_cap |= BNXT_RSS_CAP_MULTI_RSS_CTX; 10271 + bnxt_del_one_rss_ctx(bp, rss_ctx, false); 10278 10272 } 10279 10273 } 10280 10274 ··· 12299 12337 msleep(20); 12300 12338 12301 12339 if (BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) 12302 - bnxt_clear_rss_ctxs(bp, false); 12340 + bnxt_clear_rss_ctxs(bp); 12303 12341 /* Flush rings and disable interrupts */ 12304 12342 bnxt_shutdown_nic(bp, irq_re_init); 12305 12343 ··· 15214 15252 15215 15253 bnxt_free_l2_filters(bp, true); 15216 15254 bnxt_free_ntp_fltrs(bp, true); 15217 - if (BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) 15218 - bnxt_clear_rss_ctxs(bp, true); 15255 + WARN_ON(bp->num_rss_ctx); 15219 15256 clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); 15220 15257 /* Flush any pending tasks */ 15221 15258 cancel_work_sync(&bp->sp_task); ··· 15684 15723 bp->flags |= BNXT_FLAG_CHIP_P7; 15685 15724 } 15686 15725 15687 - rc = bnxt_alloc_rss_indir_tbl(bp, NULL); 15726 + rc = bnxt_alloc_rss_indir_tbl(bp); 15688 15727 if (rc) 15689 15728 goto init_err_pci_clean; 15690 15729 ··· 15841 15880 INIT_LIST_HEAD(&bp->usr_fltr_list); 15842 15881 15843 15882 if (BNXT_SUPPORTS_NTUPLE_VNIC(bp)) 15844 - bnxt_init_multi_rss_ctx(bp); 15845 - 15883 + bp->rss_cap |= BNXT_RSS_CAP_MULTI_RSS_CTX; 15846 15884 15847 15885 rc = register_netdev(dev); 15848 15886 if (rc) ··· 15864 15904 bnxt_clear_int_mode(bp); 15865 15905 15866 15906 init_err_pci_clean: 15867 - if (BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) 15868 - bnxt_clear_rss_ctxs(bp, true); 15869 15907 bnxt_hwrm_func_drv_unrgtr(bp); 15870 15908 bnxt_free_hwrm_resources(bp); 15871 15909 bnxt_hwmon_uninit(bp);
+5 -12
drivers/net/ethernet/broadcom/bnxt/bnxt.h
··· 1286 1286 #define BNXT_VNIC_RFS_NEW_RSS_FLAG 0x10 1287 1287 #define BNXT_VNIC_NTUPLE_FLAG 0x20 1288 1288 #define BNXT_VNIC_RSSCTX_FLAG 0x40 1289 - struct bnxt_rss_ctx *rss_ctx; 1289 + struct ethtool_rxfh_context *rss_ctx; 1290 1290 u32 vnic_id; 1291 1291 }; 1292 1292 1293 1293 struct bnxt_rss_ctx { 1294 - struct list_head list; 1295 1294 struct bnxt_vnic_info vnic; 1296 - u16 *rss_indir_tbl; 1297 1295 u8 index; 1298 1296 }; 1299 1297 1300 1298 #define BNXT_MAX_ETH_RSS_CTX 32 1301 - #define BNXT_RSS_CTX_BMAP_LEN (BNXT_MAX_ETH_RSS_CTX + 1) 1302 1299 #define BNXT_VNIC_ID_INVALID 0xffffffff 1303 1300 1304 1301 struct bnxt_hw_rings { ··· 2328 2331 /* grp_info indexed by completion ring index */ 2329 2332 struct bnxt_ring_grp_info *grp_info; 2330 2333 struct bnxt_vnic_info *vnic_info; 2331 - struct list_head rss_ctx_list; 2332 - unsigned long *rss_ctx_bmap; 2333 2334 u32 num_rss_ctx; 2334 2335 int nr_vnics; 2335 - u16 *rss_indir_tbl; 2336 + u32 *rss_indir_tbl; 2336 2337 u16 rss_indir_tbl_entries; 2337 2338 u32 rss_hash_cfg; 2338 2339 u32 rss_hash_delta; ··· 2807 2812 int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, struct bnxt_vnic_info *vnic, 2808 2813 u32 tpa_flags); 2809 2814 void bnxt_fill_ipv6_mask(__be32 mask[4]); 2810 - int bnxt_alloc_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx); 2811 - void bnxt_set_dflt_rss_indir_tbl(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx); 2812 - u16 bnxt_get_max_rss_ctx_ring(struct bnxt *bp); 2815 + void bnxt_set_dflt_rss_indir_tbl(struct bnxt *bp, 2816 + struct ethtool_rxfh_context *rss_ctx); 2813 2817 int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings); 2814 2818 int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic); 2815 2819 int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic, ··· 2842 2848 int __bnxt_setup_vnic_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic); 2843 2849 void bnxt_del_one_rss_ctx(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx, 2844 2850 bool all); 2845 - struct bnxt_rss_ctx *bnxt_alloc_rss_ctx(struct bnxt *bp); 2846 - void bnxt_clear_rss_ctxs(struct bnxt *bp, bool all); 2851 + void bnxt_clear_rss_ctxs(struct bnxt *bp); 2847 2852 int bnxt_open_nic(struct bnxt *, bool, bool); 2848 2853 int bnxt_half_open_nic(struct bnxt *bp); 2849 2854 void bnxt_half_close_nic(struct bnxt *bp);
+88 -77
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
··· 961 961 return rc; 962 962 } 963 963 964 - if (req_rx_rings < bp->rx_nr_rings && 965 - req_rx_rings <= bnxt_get_max_rss_ctx_ring(bp)) { 966 - netdev_warn(dev, "Can't deactivate rings used by RSS contexts\n"); 967 - return -EINVAL; 968 - } 969 - 970 964 if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != 971 965 bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) && 972 966 netif_is_rxfh_configured(dev)) { ··· 970 976 971 977 bnxt_clear_usr_fltrs(bp, true); 972 978 if (BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) 973 - bnxt_clear_rss_ctxs(bp, false); 979 + bnxt_clear_rss_ctxs(bp); 974 980 if (netif_running(dev)) { 975 981 if (BNXT_PF(bp)) { 976 982 /* TODO CHIMP_FW: Send message to all VF's ··· 1210 1216 static struct bnxt_rss_ctx *bnxt_get_rss_ctx_from_index(struct bnxt *bp, 1211 1217 u32 index) 1212 1218 { 1213 - struct bnxt_rss_ctx *rss_ctx, *tmp; 1219 + struct ethtool_rxfh_context *ctx; 1214 1220 1215 - list_for_each_entry_safe(rss_ctx, tmp, &bp->rss_ctx_list, list) 1216 - if (rss_ctx->index == index) 1217 - return rss_ctx; 1218 - return NULL; 1221 + ctx = xa_load(&bp->dev->ethtool->rss_ctx, index); 1222 + if (!ctx) 1223 + return NULL; 1224 + return ethtool_rxfh_context_priv(ctx); 1219 1225 } 1220 1226 1221 - static int bnxt_alloc_rss_ctx_rss_table(struct bnxt *bp, 1222 - struct bnxt_rss_ctx *rss_ctx) 1227 + static int bnxt_alloc_vnic_rss_table(struct bnxt *bp, 1228 + struct bnxt_vnic_info *vnic) 1223 1229 { 1224 1230 int size = L1_CACHE_ALIGN(BNXT_MAX_RSS_TABLE_SIZE_P5); 1225 - struct bnxt_vnic_info *vnic = &rss_ctx->vnic; 1226 1231 1227 1232 vnic->rss_table_size = size + HW_HASH_KEY_SIZE; 1228 1233 vnic->rss_table = dma_alloc_coherent(&bp->pdev->dev, ··· 1800 1807 static int bnxt_get_rxfh(struct net_device *dev, 1801 1808 struct ethtool_rxfh_param *rxfh) 1802 1809 { 1803 - u32 rss_context = rxfh->rss_context; 1804 1810 struct bnxt_rss_ctx *rss_ctx = NULL; 1805 1811 struct bnxt *bp = netdev_priv(dev); 1806 - u16 *indir_tbl = bp->rss_indir_tbl; 1812 + u32 *indir_tbl = bp->rss_indir_tbl; 1807 1813 struct bnxt_vnic_info *vnic; 1808 1814 u32 i, tbl_size; 1809 1815 ··· 1813 1821 1814 1822 vnic = &bp->vnic_info[BNXT_VNIC_DEFAULT]; 1815 1823 if (rxfh->rss_context) { 1816 - rss_ctx = bnxt_get_rss_ctx_from_index(bp, rss_context); 1817 - if (!rss_ctx) 1824 + struct ethtool_rxfh_context *ctx; 1825 + 1826 + ctx = xa_load(&bp->dev->ethtool->rss_ctx, rxfh->rss_context); 1827 + if (!ctx) 1818 1828 return -EINVAL; 1819 - indir_tbl = rss_ctx->rss_indir_tbl; 1829 + indir_tbl = ethtool_rxfh_context_indir(ctx); 1830 + rss_ctx = ethtool_rxfh_context_priv(ctx); 1820 1831 vnic = &rss_ctx->vnic; 1821 1832 } 1822 1833 ··· 1835 1840 return 0; 1836 1841 } 1837 1842 1838 - static void bnxt_modify_rss(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx, 1839 - struct ethtool_rxfh_param *rxfh) 1843 + static void bnxt_modify_rss(struct bnxt *bp, struct ethtool_rxfh_context *ctx, 1844 + struct bnxt_rss_ctx *rss_ctx, 1845 + const struct ethtool_rxfh_param *rxfh) 1840 1846 { 1841 1847 if (rxfh->key) { 1842 1848 if (rss_ctx) { ··· 1850 1854 } 1851 1855 if (rxfh->indir) { 1852 1856 u32 i, pad, tbl_size = bnxt_get_rxfh_indir_size(bp->dev); 1853 - u16 *indir_tbl = bp->rss_indir_tbl; 1857 + u32 *indir_tbl = bp->rss_indir_tbl; 1854 1858 1855 1859 if (rss_ctx) 1856 - indir_tbl = rss_ctx->rss_indir_tbl; 1860 + indir_tbl = ethtool_rxfh_context_indir(ctx); 1857 1861 for (i = 0; i < tbl_size; i++) 1858 1862 indir_tbl[i] = rxfh->indir[i]; 1859 1863 pad = bp->rss_indir_tbl_entries - tbl_size; 1860 1864 if (pad) 1861 - memset(&bp->rss_indir_tbl[i], 0, pad * sizeof(u16)); 1865 + memset(&indir_tbl[i], 0, pad * sizeof(*indir_tbl)); 1862 1866 } 1863 1867 } 1864 1868 1865 - static int bnxt_set_rxfh_context(struct bnxt *bp, 1866 - struct ethtool_rxfh_param *rxfh, 1867 - struct netlink_ext_ack *extack) 1869 + static int bnxt_rxfh_context_check(struct bnxt *bp, 1870 + struct netlink_ext_ack *extack) 1868 1871 { 1869 - u32 *rss_context = &rxfh->rss_context; 1870 - struct bnxt_rss_ctx *rss_ctx; 1871 - struct bnxt_vnic_info *vnic; 1872 - bool modify = false; 1873 - int bit_id; 1874 - int rc; 1875 - 1876 1872 if (!BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) { 1877 1873 NL_SET_ERR_MSG_MOD(extack, "RSS contexts not supported"); 1878 1874 return -EOPNOTSUPP; ··· 1875 1887 return -EAGAIN; 1876 1888 } 1877 1889 1878 - if (*rss_context != ETH_RXFH_CONTEXT_ALLOC) { 1879 - rss_ctx = bnxt_get_rss_ctx_from_index(bp, *rss_context); 1880 - if (!rss_ctx) { 1881 - NL_SET_ERR_MSG_FMT_MOD(extack, "RSS context %u not found", 1882 - *rss_context); 1883 - return -EINVAL; 1884 - } 1885 - if (*rss_context && rxfh->rss_delete) { 1886 - bnxt_del_one_rss_ctx(bp, rss_ctx, true); 1887 - return 0; 1888 - } 1889 - modify = true; 1890 - vnic = &rss_ctx->vnic; 1891 - goto modify_context; 1892 - } 1890 + return 0; 1891 + } 1892 + 1893 + static int bnxt_create_rxfh_context(struct net_device *dev, 1894 + struct ethtool_rxfh_context *ctx, 1895 + const struct ethtool_rxfh_param *rxfh, 1896 + struct netlink_ext_ack *extack) 1897 + { 1898 + struct bnxt *bp = netdev_priv(dev); 1899 + struct bnxt_rss_ctx *rss_ctx; 1900 + struct bnxt_vnic_info *vnic; 1901 + int rc; 1902 + 1903 + rc = bnxt_rxfh_context_check(bp, extack); 1904 + if (rc) 1905 + return rc; 1893 1906 1894 1907 if (bp->num_rss_ctx >= BNXT_MAX_ETH_RSS_CTX) { 1895 1908 NL_SET_ERR_MSG_FMT_MOD(extack, "Out of RSS contexts, maximum %u", ··· 1903 1914 return -ENOMEM; 1904 1915 } 1905 1916 1906 - rss_ctx = bnxt_alloc_rss_ctx(bp); 1907 - if (!rss_ctx) 1908 - return -ENOMEM; 1917 + rss_ctx = ethtool_rxfh_context_priv(ctx); 1918 + 1919 + bp->num_rss_ctx++; 1909 1920 1910 1921 vnic = &rss_ctx->vnic; 1922 + vnic->rss_ctx = ctx; 1911 1923 vnic->flags |= BNXT_VNIC_RSSCTX_FLAG; 1912 1924 vnic->vnic_id = BNXT_VNIC_ID_INVALID; 1913 - rc = bnxt_alloc_rss_ctx_rss_table(bp, rss_ctx); 1925 + rc = bnxt_alloc_vnic_rss_table(bp, vnic); 1914 1926 if (rc) 1915 1927 goto out; 1916 1928 1917 - rc = bnxt_alloc_rss_indir_tbl(bp, rss_ctx); 1918 - if (rc) 1919 - goto out; 1920 - 1921 - bnxt_set_dflt_rss_indir_tbl(bp, rss_ctx); 1929 + bnxt_set_dflt_rss_indir_tbl(bp, ctx); 1922 1930 memcpy(vnic->rss_hash_key, bp->rss_hash_key, HW_HASH_KEY_SIZE); 1923 1931 1924 1932 rc = bnxt_hwrm_vnic_alloc(bp, vnic, 0, bp->rx_nr_rings); ··· 1929 1943 NL_SET_ERR_MSG_MOD(extack, "Unable to setup TPA"); 1930 1944 goto out; 1931 1945 } 1932 - modify_context: 1933 - bnxt_modify_rss(bp, rss_ctx, rxfh); 1934 - 1935 - if (modify) 1936 - return bnxt_hwrm_vnic_rss_cfg_p5(bp, vnic); 1946 + bnxt_modify_rss(bp, ctx, rss_ctx, rxfh); 1937 1947 1938 1948 rc = __bnxt_setup_vnic_p5(bp, vnic); 1939 1949 if (rc) { ··· 1937 1955 goto out; 1938 1956 } 1939 1957 1940 - bit_id = bitmap_find_free_region(bp->rss_ctx_bmap, 1941 - BNXT_RSS_CTX_BMAP_LEN, 0); 1942 - if (bit_id < 0) { 1943 - rc = -ENOMEM; 1944 - goto out; 1945 - } 1946 - rss_ctx->index = (u16)bit_id; 1947 - *rss_context = rss_ctx->index; 1948 - 1958 + rss_ctx->index = rxfh->rss_context; 1949 1959 return 0; 1950 1960 out: 1951 1961 bnxt_del_one_rss_ctx(bp, rss_ctx, true); 1952 1962 return rc; 1963 + } 1964 + 1965 + static int bnxt_modify_rxfh_context(struct net_device *dev, 1966 + struct ethtool_rxfh_context *ctx, 1967 + const struct ethtool_rxfh_param *rxfh, 1968 + struct netlink_ext_ack *extack) 1969 + { 1970 + struct bnxt *bp = netdev_priv(dev); 1971 + struct bnxt_rss_ctx *rss_ctx; 1972 + int rc; 1973 + 1974 + rc = bnxt_rxfh_context_check(bp, extack); 1975 + if (rc) 1976 + return rc; 1977 + 1978 + rss_ctx = ethtool_rxfh_context_priv(ctx); 1979 + 1980 + bnxt_modify_rss(bp, ctx, rss_ctx, rxfh); 1981 + 1982 + return bnxt_hwrm_vnic_rss_cfg_p5(bp, &rss_ctx->vnic); 1983 + } 1984 + 1985 + static int bnxt_remove_rxfh_context(struct net_device *dev, 1986 + struct ethtool_rxfh_context *ctx, 1987 + u32 rss_context, 1988 + struct netlink_ext_ack *extack) 1989 + { 1990 + struct bnxt *bp = netdev_priv(dev); 1991 + struct bnxt_rss_ctx *rss_ctx; 1992 + 1993 + rss_ctx = ethtool_rxfh_context_priv(ctx); 1994 + 1995 + bnxt_del_one_rss_ctx(bp, rss_ctx, true); 1996 + return 0; 1953 1997 } 1954 1998 1955 1999 static int bnxt_set_rxfh(struct net_device *dev, ··· 1988 1980 if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP) 1989 1981 return -EOPNOTSUPP; 1990 1982 1991 - if (rxfh->rss_context) 1992 - return bnxt_set_rxfh_context(bp, rxfh, extack); 1993 - 1994 - bnxt_modify_rss(bp, NULL, rxfh); 1983 + bnxt_modify_rss(bp, NULL, NULL, rxfh); 1995 1984 1996 1985 bnxt_clear_usr_fltrs(bp, false); 1997 1986 if (netif_running(bp->dev)) { ··· 5280 5275 const struct ethtool_ops bnxt_ethtool_ops = { 5281 5276 .cap_link_lanes_supported = 1, 5282 5277 .cap_rss_ctx_supported = 1, 5278 + .rxfh_max_context_id = BNXT_MAX_ETH_RSS_CTX, 5279 + .rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5, 5280 + .rxfh_priv_size = sizeof(struct bnxt_rss_ctx), 5283 5281 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 5284 5282 ETHTOOL_COALESCE_MAX_FRAMES | 5285 5283 ETHTOOL_COALESCE_USECS_IRQ | ··· 5320 5312 .get_rxfh_key_size = bnxt_get_rxfh_key_size, 5321 5313 .get_rxfh = bnxt_get_rxfh, 5322 5314 .set_rxfh = bnxt_set_rxfh, 5315 + .create_rxfh_context = bnxt_create_rxfh_context, 5316 + .modify_rxfh_context = bnxt_modify_rxfh_context, 5317 + .remove_rxfh_context = bnxt_remove_rxfh_context, 5323 5318 .flash_device = bnxt_flash_device, 5324 5319 .get_eeprom_len = bnxt_get_eeprom_len, 5325 5320 .get_eeprom = bnxt_get_eeprom,
+9 -11
include/linux/ethtool.h
··· 181 181 /* private: driver private data, indirection table, and hash key are 182 182 * stored sequentially in @data area. Use below helpers to access. 183 183 */ 184 + u32 key_off; 184 185 u8 data[] __aligned(sizeof(void *)); 185 186 }; 186 187 ··· 197 196 198 197 static inline u8 *ethtool_rxfh_context_key(struct ethtool_rxfh_context *ctx) 199 198 { 200 - return (u8 *)(ethtool_rxfh_context_indir(ctx) + ctx->indir_size); 199 + return &ctx->data[ctx->key_off]; 201 200 } 202 201 203 - static inline size_t ethtool_rxfh_context_size(u32 indir_size, u32 key_size, 204 - u16 priv_size) 205 - { 206 - size_t indir_bytes = array_size(indir_size, sizeof(u32)); 207 - size_t flex_len; 208 - 209 - flex_len = size_add(size_add(indir_bytes, key_size), 210 - ALIGN(priv_size, sizeof(u32))); 211 - return struct_size_t(struct ethtool_rxfh_context, data, flex_len); 212 - } 202 + void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id); 213 203 214 204 /* declare a link mode bitmap */ 215 205 #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \ ··· 713 721 * contexts. 714 722 * @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor 715 723 * RSS. 724 + * @rxfh_indir_space: max size of RSS indirection tables, if indirection table 725 + * size as returned by @get_rxfh_indir_size may change during lifetime 726 + * of the device. Leave as 0 if the table size is constant. 727 + * @rxfh_key_space: same as @rxfh_indir_space, but for the key. 716 728 * @rxfh_priv_size: size of the driver private data area the core should 717 729 * allocate for an RSS context (in &struct ethtool_rxfh_context). 718 730 * @rxfh_max_context_id: maximum (exclusive) supported RSS context ID. If this ··· 934 938 u32 cap_link_lanes_supported:1; 935 939 u32 cap_rss_ctx_supported:1; 936 940 u32 cap_rss_sym_xor_supported:1; 941 + u32 rxfh_indir_space; 942 + u16 rxfh_key_space; 937 943 u16 rxfh_priv_size; 938 944 u32 rxfh_max_context_id; 939 945 u32 supported_coalesce_params;
+14
net/ethtool/common.c
··· 741 741 } 742 742 } 743 743 EXPORT_SYMBOL_GPL(ethtool_forced_speed_maps_init); 744 + 745 + void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id) 746 + { 747 + struct ethtool_rxfh_context *ctx; 748 + 749 + WARN_ONCE(!rtnl_is_locked() && 750 + !lockdep_is_held_type(&dev->ethtool->rss_lock, -1), 751 + "RSS context lock assertion failed\n"); 752 + 753 + netdev_err(dev, "device error, RSS context %d lost\n", context_id); 754 + ctx = xa_erase(&dev->ethtool->rss_ctx, context_id); 755 + kfree(ctx); 756 + } 757 + EXPORT_SYMBOL(ethtool_rxfh_context_lost);
+36 -10
net/ethtool/ioctl.c
··· 1290 1290 return ret; 1291 1291 } 1292 1292 1293 + static struct ethtool_rxfh_context * 1294 + ethtool_rxfh_ctx_alloc(const struct ethtool_ops *ops, 1295 + u32 indir_size, u32 key_size) 1296 + { 1297 + size_t indir_bytes, flex_len, key_off, size; 1298 + struct ethtool_rxfh_context *ctx; 1299 + u32 priv_bytes, indir_max; 1300 + u16 key_max; 1301 + 1302 + key_max = max(key_size, ops->rxfh_key_space); 1303 + indir_max = max(indir_size, ops->rxfh_indir_space); 1304 + 1305 + priv_bytes = ALIGN(ops->rxfh_priv_size, sizeof(u32)); 1306 + indir_bytes = array_size(indir_max, sizeof(u32)); 1307 + 1308 + key_off = size_add(priv_bytes, indir_bytes); 1309 + flex_len = size_add(key_off, key_max); 1310 + size = struct_size_t(struct ethtool_rxfh_context, data, flex_len); 1311 + 1312 + ctx = kzalloc(size, GFP_KERNEL_ACCOUNT); 1313 + if (!ctx) 1314 + return NULL; 1315 + 1316 + ctx->indir_size = indir_size; 1317 + ctx->key_size = key_size; 1318 + ctx->key_off = key_off; 1319 + ctx->priv_size = ops->rxfh_priv_size; 1320 + 1321 + ctx->hfunc = ETH_RSS_HASH_NO_CHANGE; 1322 + ctx->input_xfrm = RXH_XFRM_NO_CHANGE; 1323 + 1324 + return ctx; 1325 + } 1326 + 1293 1327 static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, 1294 1328 void __user *useraddr) 1295 1329 { ··· 1440 1406 ret = -EINVAL; 1441 1407 goto out; 1442 1408 } 1443 - ctx = kzalloc(ethtool_rxfh_context_size(dev_indir_size, 1444 - dev_key_size, 1445 - ops->rxfh_priv_size), 1446 - GFP_KERNEL_ACCOUNT); 1409 + ctx = ethtool_rxfh_ctx_alloc(ops, dev_indir_size, dev_key_size); 1447 1410 if (!ctx) { 1448 1411 ret = -ENOMEM; 1449 1412 goto out; 1450 1413 } 1451 - ctx->indir_size = dev_indir_size; 1452 - ctx->key_size = dev_key_size; 1453 - ctx->priv_size = ops->rxfh_priv_size; 1454 - /* Initialise to an empty context */ 1455 - ctx->hfunc = ETH_RSS_HASH_NO_CHANGE; 1456 - ctx->input_xfrm = RXH_XFRM_NO_CHANGE; 1414 + 1457 1415 if (ops->create_rxfh_context) { 1458 1416 u32 limit = ops->rxfh_max_context_id ?: U32_MAX; 1459 1417 u32 ctx_id;