diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 117 |
1 files changed, 85 insertions, 32 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0d592f7c3a99..03c47cf04e90 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -360,6 +360,8 @@ bnx2_netif_start(struct bnx2 *bp) | |||
360 | static void | 360 | static void |
361 | bnx2_free_mem(struct bnx2 *bp) | 361 | bnx2_free_mem(struct bnx2 *bp) |
362 | { | 362 | { |
363 | int i; | ||
364 | |||
363 | if (bp->stats_blk) { | 365 | if (bp->stats_blk) { |
364 | pci_free_consistent(bp->pdev, sizeof(struct statistics_block), | 366 | pci_free_consistent(bp->pdev, sizeof(struct statistics_block), |
365 | bp->stats_blk, bp->stats_blk_mapping); | 367 | bp->stats_blk, bp->stats_blk_mapping); |
@@ -378,19 +380,23 @@ bnx2_free_mem(struct bnx2 *bp) | |||
378 | } | 380 | } |
379 | kfree(bp->tx_buf_ring); | 381 | kfree(bp->tx_buf_ring); |
380 | bp->tx_buf_ring = NULL; | 382 | bp->tx_buf_ring = NULL; |
381 | if (bp->rx_desc_ring) { | 383 | for (i = 0; i < bp->rx_max_ring; i++) { |
382 | pci_free_consistent(bp->pdev, | 384 | if (bp->rx_desc_ring[i]) |
383 | sizeof(struct rx_bd) * RX_DESC_CNT, | 385 | pci_free_consistent(bp->pdev, |
384 | bp->rx_desc_ring, bp->rx_desc_mapping); | 386 | sizeof(struct rx_bd) * RX_DESC_CNT, |
385 | bp->rx_desc_ring = NULL; | 387 | bp->rx_desc_ring[i], |
386 | } | 388 | bp->rx_desc_mapping[i]); |
387 | kfree(bp->rx_buf_ring); | 389 | bp->rx_desc_ring[i] = NULL; |
390 | } | ||
391 | vfree(bp->rx_buf_ring); | ||
388 | bp->rx_buf_ring = NULL; | 392 | bp->rx_buf_ring = NULL; |
389 | } | 393 | } |
390 | 394 | ||
391 | static int | 395 | static int |
392 | bnx2_alloc_mem(struct bnx2 *bp) | 396 | bnx2_alloc_mem(struct bnx2 *bp) |
393 | { | 397 | { |
398 | int i; | ||
399 | |||
394 | bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, | 400 | bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, |
395 | GFP_KERNEL); | 401 | GFP_KERNEL); |
396 | if (bp->tx_buf_ring == NULL) | 402 | if (bp->tx_buf_ring == NULL) |
@@ -404,18 +410,23 @@ bnx2_alloc_mem(struct bnx2 *bp) | |||
404 | if (bp->tx_desc_ring == NULL) | 410 | if (bp->tx_desc_ring == NULL) |
405 | goto alloc_mem_err; | 411 | goto alloc_mem_err; |
406 | 412 | ||
407 | bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT, | 413 | bp->rx_buf_ring = vmalloc(sizeof(struct sw_bd) * RX_DESC_CNT * |
408 | GFP_KERNEL); | 414 | bp->rx_max_ring); |
409 | if (bp->rx_buf_ring == NULL) | 415 | if (bp->rx_buf_ring == NULL) |
410 | goto alloc_mem_err; | 416 | goto alloc_mem_err; |
411 | 417 | ||
412 | memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT); | 418 | memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT * |
413 | bp->rx_desc_ring = pci_alloc_consistent(bp->pdev, | 419 | bp->rx_max_ring); |
414 | sizeof(struct rx_bd) * | 420 | |
415 | RX_DESC_CNT, | 421 | for (i = 0; i < bp->rx_max_ring; i++) { |
416 | &bp->rx_desc_mapping); | 422 | bp->rx_desc_ring[i] = |
417 | if (bp->rx_desc_ring == NULL) | 423 | pci_alloc_consistent(bp->pdev, |
418 | goto alloc_mem_err; | 424 | sizeof(struct rx_bd) * RX_DESC_CNT, |
425 | &bp->rx_desc_mapping[i]); | ||
426 | if (bp->rx_desc_ring[i] == NULL) | ||
427 | goto alloc_mem_err; | ||
428 | |||
429 | } | ||
419 | 430 | ||
420 | bp->status_blk = pci_alloc_consistent(bp->pdev, | 431 | bp->status_blk = pci_alloc_consistent(bp->pdev, |
421 | sizeof(struct status_block), | 432 | sizeof(struct status_block), |
@@ -1520,7 +1531,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) | |||
1520 | struct sk_buff *skb; | 1531 | struct sk_buff *skb; |
1521 | struct sw_bd *rx_buf = &bp->rx_buf_ring[index]; | 1532 | struct sw_bd *rx_buf = &bp->rx_buf_ring[index]; |
1522 | dma_addr_t mapping; | 1533 | dma_addr_t mapping; |
1523 | struct rx_bd *rxbd = &bp->rx_desc_ring[index]; | 1534 | struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; |
1524 | unsigned long align; | 1535 | unsigned long align; |
1525 | 1536 | ||
1526 | skb = dev_alloc_skb(bp->rx_buf_size); | 1537 | skb = dev_alloc_skb(bp->rx_buf_size); |
@@ -3349,24 +3360,32 @@ bnx2_init_rx_ring(struct bnx2 *bp) | |||
3349 | bp->hw_rx_cons = 0; | 3360 | bp->hw_rx_cons = 0; |
3350 | bp->rx_prod_bseq = 0; | 3361 | bp->rx_prod_bseq = 0; |
3351 | 3362 | ||
3352 | rxbd = &bp->rx_desc_ring[0]; | 3363 | for (i = 0; i < bp->rx_max_ring; i++) { |
3353 | for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { | 3364 | int j; |
3354 | rxbd->rx_bd_len = bp->rx_buf_use_size; | ||
3355 | rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; | ||
3356 | } | ||
3357 | 3365 | ||
3358 | rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32; | 3366 | rxbd = &bp->rx_desc_ring[i][0]; |
3359 | rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff; | 3367 | for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) { |
3368 | rxbd->rx_bd_len = bp->rx_buf_use_size; | ||
3369 | rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; | ||
3370 | } | ||
3371 | if (i == (bp->rx_max_ring - 1)) | ||
3372 | j = 0; | ||
3373 | else | ||
3374 | j = i + 1; | ||
3375 | rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping[j] >> 32; | ||
3376 | rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping[j] & | ||
3377 | 0xffffffff; | ||
3378 | } | ||
3360 | 3379 | ||
3361 | val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; | 3380 | val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; |
3362 | val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; | 3381 | val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; |
3363 | val |= 0x02 << 8; | 3382 | val |= 0x02 << 8; |
3364 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val); | 3383 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val); |
3365 | 3384 | ||
3366 | val = (u64) bp->rx_desc_mapping >> 32; | 3385 | val = (u64) bp->rx_desc_mapping[0] >> 32; |
3367 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val); | 3386 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val); |
3368 | 3387 | ||
3369 | val = (u64) bp->rx_desc_mapping & 0xffffffff; | 3388 | val = (u64) bp->rx_desc_mapping[0] & 0xffffffff; |
3370 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); | 3389 | CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); |
3371 | 3390 | ||
3372 | for (i = 0; i < bp->rx_ring_size; i++) { | 3391 | for (i = 0; i < bp->rx_ring_size; i++) { |
@@ -3384,6 +3403,29 @@ bnx2_init_rx_ring(struct bnx2 *bp) | |||
3384 | } | 3403 | } |
3385 | 3404 | ||
3386 | static void | 3405 | static void |
3406 | bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) | ||
3407 | { | ||
3408 | u32 num_rings, max; | ||
3409 | |||
3410 | bp->rx_ring_size = size; | ||
3411 | num_rings = 1; | ||
3412 | while (size > MAX_RX_DESC_CNT) { | ||
3413 | size -= MAX_RX_DESC_CNT; | ||
3414 | num_rings++; | ||
3415 | } | ||
3416 | /* round to next power of 2 */ | ||
3417 | max = MAX_RX_RINGS; | ||
3418 | while ((max & num_rings) == 0) | ||
3419 | max >>= 1; | ||
3420 | |||
3421 | if (num_rings != max) | ||
3422 | max <<= 1; | ||
3423 | |||
3424 | bp->rx_max_ring = max; | ||
3425 | bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1; | ||
3426 | } | ||
3427 | |||
3428 | static void | ||
3387 | bnx2_free_tx_skbs(struct bnx2 *bp) | 3429 | bnx2_free_tx_skbs(struct bnx2 *bp) |
3388 | { | 3430 | { |
3389 | int i; | 3431 | int i; |
@@ -3428,7 +3470,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp) | |||
3428 | if (bp->rx_buf_ring == NULL) | 3470 | if (bp->rx_buf_ring == NULL) |
3429 | return; | 3471 | return; |
3430 | 3472 | ||
3431 | for (i = 0; i < RX_DESC_CNT; i++) { | 3473 | for (i = 0; i < bp->rx_max_ring_idx; i++) { |
3432 | struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; | 3474 | struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; |
3433 | struct sk_buff *skb = rx_buf->skb; | 3475 | struct sk_buff *skb = rx_buf->skb; |
3434 | 3476 | ||
@@ -4792,7 +4834,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) | |||
4792 | { | 4834 | { |
4793 | struct bnx2 *bp = netdev_priv(dev); | 4835 | struct bnx2 *bp = netdev_priv(dev); |
4794 | 4836 | ||
4795 | ering->rx_max_pending = MAX_RX_DESC_CNT; | 4837 | ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT; |
4796 | ering->rx_mini_max_pending = 0; | 4838 | ering->rx_mini_max_pending = 0; |
4797 | ering->rx_jumbo_max_pending = 0; | 4839 | ering->rx_jumbo_max_pending = 0; |
4798 | 4840 | ||
@@ -4809,17 +4851,28 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) | |||
4809 | { | 4851 | { |
4810 | struct bnx2 *bp = netdev_priv(dev); | 4852 | struct bnx2 *bp = netdev_priv(dev); |
4811 | 4853 | ||
4812 | if ((ering->rx_pending > MAX_RX_DESC_CNT) || | 4854 | if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) || |
4813 | (ering->tx_pending > MAX_TX_DESC_CNT) || | 4855 | (ering->tx_pending > MAX_TX_DESC_CNT) || |
4814 | (ering->tx_pending <= MAX_SKB_FRAGS)) { | 4856 | (ering->tx_pending <= MAX_SKB_FRAGS)) { |
4815 | 4857 | ||
4816 | return -EINVAL; | 4858 | return -EINVAL; |
4817 | } | 4859 | } |
4818 | bp->rx_ring_size = ering->rx_pending; | 4860 | if (netif_running(bp->dev)) { |
4861 | bnx2_netif_stop(bp); | ||
4862 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); | ||
4863 | bnx2_free_skbs(bp); | ||
4864 | bnx2_free_mem(bp); | ||
4865 | } | ||
4866 | |||
4867 | bnx2_set_rx_ring_size(bp, ering->rx_pending); | ||
4819 | bp->tx_ring_size = ering->tx_pending; | 4868 | bp->tx_ring_size = ering->tx_pending; |
4820 | 4869 | ||
4821 | if (netif_running(bp->dev)) { | 4870 | if (netif_running(bp->dev)) { |
4822 | bnx2_netif_stop(bp); | 4871 | int rc; |
4872 | |||
4873 | rc = bnx2_alloc_mem(bp); | ||
4874 | if (rc) | ||
4875 | return rc; | ||
4823 | bnx2_init_nic(bp); | 4876 | bnx2_init_nic(bp); |
4824 | bnx2_netif_start(bp); | 4877 | bnx2_netif_start(bp); |
4825 | } | 4878 | } |
@@ -5493,7 +5546,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
5493 | bp->mac_addr[5] = (u8) reg; | 5546 | bp->mac_addr[5] = (u8) reg; |
5494 | 5547 | ||
5495 | bp->tx_ring_size = MAX_TX_DESC_CNT; | 5548 | bp->tx_ring_size = MAX_TX_DESC_CNT; |
5496 | bp->rx_ring_size = 100; | 5549 | bnx2_set_rx_ring_size(bp, 100); |
5497 | 5550 | ||
5498 | bp->rx_csum = 1; | 5551 | bp->rx_csum = 1; |
5499 | 5552 | ||