diff options
author | David S. Miller <davem@davemloft.net> | 2017-07-11 13:32:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-07-11 13:32:12 -0400 |
commit | 4c17e1febd73c3b2467fd9f67e0017a82805196a (patch) | |
tree | e2a43c742866d3e36b86a9c2bcc4513f426a997d | |
parent | de92cd6cf4899c0876a8f5519769a786ad7cdeea (diff) | |
parent | 9b0436c3f29483ca91d890b0072c0c02e2e535ed (diff) |
Merge branch 'bnxt_en-Bug-fixes'
Michael Chan says:
====================
bnxt_en: Bug fixes.
3 bug fixes in this series. Fix a crash in bnxt_get_stats64() that can
happen if the device is closing and freeing the statistics block at the
same time. The 2nd one fixes ethtool -L failing when changing from
combined to non-combined mode or vice versa. The last one fixes SRIOV
failure on big-endian systems because we were setting a bitmap wrong in
a firmware message.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnxt/bnxt.c | 42 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 2 |
4 files changed, 35 insertions, 16 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index a19f68f5862d..e7c8539cbddf 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c | |||
@@ -3458,13 +3458,18 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) | |||
3458 | req.ver_upd = DRV_VER_UPD; | 3458 | req.ver_upd = DRV_VER_UPD; |
3459 | 3459 | ||
3460 | if (BNXT_PF(bp)) { | 3460 | if (BNXT_PF(bp)) { |
3461 | DECLARE_BITMAP(vf_req_snif_bmap, 256); | 3461 | u32 data[8]; |
3462 | u32 *data = (u32 *)vf_req_snif_bmap; | ||
3463 | int i; | 3462 | int i; |
3464 | 3463 | ||
3465 | memset(vf_req_snif_bmap, 0, sizeof(vf_req_snif_bmap)); | 3464 | memset(data, 0, sizeof(data)); |
3466 | for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++) | 3465 | for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++) { |
3467 | __set_bit(bnxt_vf_req_snif[i], vf_req_snif_bmap); | 3466 | u16 cmd = bnxt_vf_req_snif[i]; |
3467 | unsigned int bit, idx; | ||
3468 | |||
3469 | idx = cmd / 32; | ||
3470 | bit = cmd % 32; | ||
3471 | data[idx] |= 1 << bit; | ||
3472 | } | ||
3468 | 3473 | ||
3469 | for (i = 0; i < 8; i++) | 3474 | for (i = 0; i < 8; i++) |
3470 | req.vf_req_fwd[i] = cpu_to_le32(data[i]); | 3475 | req.vf_req_fwd[i] = cpu_to_le32(data[i]); |
@@ -6279,6 +6284,12 @@ static int bnxt_open(struct net_device *dev) | |||
6279 | return __bnxt_open_nic(bp, true, true); | 6284 | return __bnxt_open_nic(bp, true, true); |
6280 | } | 6285 | } |
6281 | 6286 | ||
6287 | static bool bnxt_drv_busy(struct bnxt *bp) | ||
6288 | { | ||
6289 | return (test_bit(BNXT_STATE_IN_SP_TASK, &bp->state) || | ||
6290 | test_bit(BNXT_STATE_READ_STATS, &bp->state)); | ||
6291 | } | ||
6292 | |||
6282 | int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) | 6293 | int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) |
6283 | { | 6294 | { |
6284 | int rc = 0; | 6295 | int rc = 0; |
@@ -6297,7 +6308,7 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) | |||
6297 | 6308 | ||
6298 | clear_bit(BNXT_STATE_OPEN, &bp->state); | 6309 | clear_bit(BNXT_STATE_OPEN, &bp->state); |
6299 | smp_mb__after_atomic(); | 6310 | smp_mb__after_atomic(); |
6300 | while (test_bit(BNXT_STATE_IN_SP_TASK, &bp->state)) | 6311 | while (bnxt_drv_busy(bp)) |
6301 | msleep(20); | 6312 | msleep(20); |
6302 | 6313 | ||
6303 | /* Flush rings and and disable interrupts */ | 6314 | /* Flush rings and and disable interrupts */ |
@@ -6358,8 +6369,15 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | |||
6358 | u32 i; | 6369 | u32 i; |
6359 | struct bnxt *bp = netdev_priv(dev); | 6370 | struct bnxt *bp = netdev_priv(dev); |
6360 | 6371 | ||
6361 | if (!bp->bnapi) | 6372 | set_bit(BNXT_STATE_READ_STATS, &bp->state); |
6373 | /* Make sure bnxt_close_nic() sees that we are reading stats before | ||
6374 | * we check the BNXT_STATE_OPEN flag. | ||
6375 | */ | ||
6376 | smp_mb__after_atomic(); | ||
6377 | if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { | ||
6378 | clear_bit(BNXT_STATE_READ_STATS, &bp->state); | ||
6362 | return; | 6379 | return; |
6380 | } | ||
6363 | 6381 | ||
6364 | /* TODO check if we need to synchronize with bnxt_close path */ | 6382 | /* TODO check if we need to synchronize with bnxt_close path */ |
6365 | for (i = 0; i < bp->cp_nr_rings; i++) { | 6383 | for (i = 0; i < bp->cp_nr_rings; i++) { |
@@ -6406,6 +6424,7 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | |||
6406 | stats->tx_fifo_errors = le64_to_cpu(tx->tx_fifo_underruns); | 6424 | stats->tx_fifo_errors = le64_to_cpu(tx->tx_fifo_underruns); |
6407 | stats->tx_errors = le64_to_cpu(tx->tx_err); | 6425 | stats->tx_errors = le64_to_cpu(tx->tx_err); |
6408 | } | 6426 | } |
6427 | clear_bit(BNXT_STATE_READ_STATS, &bp->state); | ||
6409 | } | 6428 | } |
6410 | 6429 | ||
6411 | static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask) | 6430 | static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask) |
@@ -6904,16 +6923,13 @@ static void bnxt_sp_task(struct work_struct *work) | |||
6904 | } | 6923 | } |
6905 | 6924 | ||
6906 | /* Under rtnl_lock */ | 6925 | /* Under rtnl_lock */ |
6907 | int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp) | 6926 | int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs, |
6927 | int tx_xdp) | ||
6908 | { | 6928 | { |
6909 | int max_rx, max_tx, tx_sets = 1; | 6929 | int max_rx, max_tx, tx_sets = 1; |
6910 | int tx_rings_needed; | 6930 | int tx_rings_needed; |
6911 | bool sh = true; | ||
6912 | int rc; | 6931 | int rc; |
6913 | 6932 | ||
6914 | if (!(bp->flags & BNXT_FLAG_SHARED_RINGS)) | ||
6915 | sh = false; | ||
6916 | |||
6917 | if (tcs) | 6933 | if (tcs) |
6918 | tx_sets = tcs; | 6934 | tx_sets = tcs; |
6919 | 6935 | ||
@@ -7121,7 +7137,7 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc) | |||
7121 | sh = true; | 7137 | sh = true; |
7122 | 7138 | ||
7123 | rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, | 7139 | rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, |
7124 | tc, bp->tx_nr_rings_xdp); | 7140 | sh, tc, bp->tx_nr_rings_xdp); |
7125 | if (rc) | 7141 | if (rc) |
7126 | return rc; | 7142 | return rc; |
7127 | 7143 | ||
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index f872a7db2ca8..f34691f85602 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h | |||
@@ -1117,6 +1117,7 @@ struct bnxt { | |||
1117 | unsigned long state; | 1117 | unsigned long state; |
1118 | #define BNXT_STATE_OPEN 0 | 1118 | #define BNXT_STATE_OPEN 0 |
1119 | #define BNXT_STATE_IN_SP_TASK 1 | 1119 | #define BNXT_STATE_IN_SP_TASK 1 |
1120 | #define BNXT_STATE_READ_STATS 2 | ||
1120 | 1121 | ||
1121 | struct bnxt_irq *irq_tbl; | 1122 | struct bnxt_irq *irq_tbl; |
1122 | int total_irqs; | 1123 | int total_irqs; |
@@ -1300,7 +1301,8 @@ int bnxt_open_nic(struct bnxt *, bool, bool); | |||
1300 | int bnxt_half_open_nic(struct bnxt *bp); | 1301 | int bnxt_half_open_nic(struct bnxt *bp); |
1301 | void bnxt_half_close_nic(struct bnxt *bp); | 1302 | void bnxt_half_close_nic(struct bnxt *bp); |
1302 | int bnxt_close_nic(struct bnxt *, bool, bool); | 1303 | int bnxt_close_nic(struct bnxt *, bool, bool); |
1303 | int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, int tcs, int tx_xdp); | 1304 | int bnxt_reserve_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs, |
1305 | int tx_xdp); | ||
1304 | int bnxt_setup_mq_tc(struct net_device *dev, u8 tc); | 1306 | int bnxt_setup_mq_tc(struct net_device *dev, u8 tc); |
1305 | int bnxt_get_max_rings(struct bnxt *, int *, int *, bool); | 1307 | int bnxt_get_max_rings(struct bnxt *, int *, int *, bool); |
1306 | void bnxt_restore_pf_fw_resources(struct bnxt *bp); | 1308 | void bnxt_restore_pf_fw_resources(struct bnxt *bp); |
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index fd1181510b65..be6acadcb202 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | |||
@@ -432,7 +432,8 @@ static int bnxt_set_channels(struct net_device *dev, | |||
432 | } | 432 | } |
433 | tx_xdp = req_rx_rings; | 433 | tx_xdp = req_rx_rings; |
434 | } | 434 | } |
435 | rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, tcs, tx_xdp); | 435 | rc = bnxt_reserve_rings(bp, req_tx_rings, req_rx_rings, sh, tcs, |
436 | tx_xdp); | ||
436 | if (rc) { | 437 | if (rc) { |
437 | netdev_warn(dev, "Unable to allocate the requested rings\n"); | 438 | netdev_warn(dev, "Unable to allocate the requested rings\n"); |
438 | return rc; | 439 | return rc; |
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index 7d67552e70d7..3961a6807454 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | |||
@@ -170,7 +170,7 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) | |||
170 | if (!tc) | 170 | if (!tc) |
171 | tc = 1; | 171 | tc = 1; |
172 | rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, | 172 | rc = bnxt_reserve_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, |
173 | tc, tx_xdp); | 173 | true, tc, tx_xdp); |
174 | if (rc) { | 174 | if (rc) { |
175 | netdev_warn(dev, "Unable to reserve enough TX rings to support XDP.\n"); | 175 | netdev_warn(dev, "Unable to reserve enough TX rings to support XDP.\n"); |
176 | return rc; | 176 | return rc; |