aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-12-12 14:19:12 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:30 -0500
commit47bf4246a357d36762c9e7c282d7307152eb92e1 (patch)
tree91f28518be9daf3a2e26efd9efa9bdbb4b664454 /drivers/net/bnx2.c
parent110d0ef9907b519fed1607c73b3ae883f270561e (diff)
[BNX2]: Add init. code to handle RX pages.
Add new fields to keep track of the pages and the page rings. Add functions to allocate and free pages. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c104
1 files changed, 102 insertions, 2 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index db3b7503bb16..38e8e31cabf3 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -483,6 +483,16 @@ bnx2_free_mem(struct bnx2 *bp)
483 } 483 }
484 vfree(bp->rx_buf_ring); 484 vfree(bp->rx_buf_ring);
485 bp->rx_buf_ring = NULL; 485 bp->rx_buf_ring = NULL;
486 for (i = 0; i < bp->rx_max_pg_ring; i++) {
487 if (bp->rx_pg_desc_ring[i])
488 pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
489 bp->rx_pg_desc_ring[i],
490 bp->rx_pg_desc_mapping[i]);
491 bp->rx_pg_desc_ring[i] = NULL;
492 }
493 if (bp->rx_pg_ring)
494 vfree(bp->rx_pg_ring);
495 bp->rx_pg_ring = NULL;
486} 496}
487 497
488static int 498static int
@@ -514,6 +524,25 @@ bnx2_alloc_mem(struct bnx2 *bp)
514 524
515 } 525 }
516 526
527 if (bp->rx_pg_ring_size) {
528 bp->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
529 bp->rx_max_pg_ring);
530 if (bp->rx_pg_ring == NULL)
531 goto alloc_mem_err;
532
533 memset(bp->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
534 bp->rx_max_pg_ring);
535 }
536
537 for (i = 0; i < bp->rx_max_pg_ring; i++) {
538 bp->rx_pg_desc_ring[i] =
539 pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
540 &bp->rx_pg_desc_mapping[i]);
541 if (bp->rx_pg_desc_ring[i] == NULL)
542 goto alloc_mem_err;
543
544 }
545
517 /* Combine status and statistics blocks into one allocation. */ 546 /* Combine status and statistics blocks into one allocation. */
518 status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); 547 status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
519 bp->status_stats_size = status_blk_size + 548 bp->status_stats_size = status_blk_size +
@@ -2195,6 +2224,42 @@ bnx2_set_mac_addr(struct bnx2 *bp)
2195} 2224}
2196 2225
2197static inline int 2226static inline int
2227bnx2_alloc_rx_page(struct bnx2 *bp, u16 index)
2228{
2229 dma_addr_t mapping;
2230 struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
2231 struct rx_bd *rxbd =
2232 &bp->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
2233 struct page *page = alloc_page(GFP_ATOMIC);
2234
2235 if (!page)
2236 return -ENOMEM;
2237 mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
2238 PCI_DMA_FROMDEVICE);
2239 rx_pg->page = page;
2240 pci_unmap_addr_set(rx_pg, mapping, mapping);
2241 rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
2242 rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
2243 return 0;
2244}
2245
2246static void
2247bnx2_free_rx_page(struct bnx2 *bp, u16 index)
2248{
2249 struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
2250 struct page *page = rx_pg->page;
2251
2252 if (!page)
2253 return;
2254
2255 pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping), PAGE_SIZE,
2256 PCI_DMA_FROMDEVICE);
2257
2258 __free_page(page);
2259 rx_pg->page = NULL;
2260}
2261
2262static inline int
2198bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) 2263bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
2199{ 2264{
2200 struct sk_buff *skb; 2265 struct sk_buff *skb;
@@ -4213,11 +4278,31 @@ bnx2_init_rx_ring(struct bnx2 *bp)
4213 bp->rx_prod = 0; 4278 bp->rx_prod = 0;
4214 bp->rx_cons = 0; 4279 bp->rx_cons = 0;
4215 bp->rx_prod_bseq = 0; 4280 bp->rx_prod_bseq = 0;
4281 bp->rx_pg_prod = 0;
4282 bp->rx_pg_cons = 0;
4216 4283
4217 bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping, 4284 bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping,
4218 bp->rx_buf_use_size, bp->rx_max_ring); 4285 bp->rx_buf_use_size, bp->rx_max_ring);
4219 4286
4220 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0); 4287 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
4288 if (bp->rx_pg_ring_size) {
4289 bnx2_init_rxbd_rings(bp->rx_pg_desc_ring,
4290 bp->rx_pg_desc_mapping,
4291 PAGE_SIZE, bp->rx_max_pg_ring);
4292 val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
4293 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
4294 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
4295 BNX2_L2CTX_RBDC_JUMBO_KEY);
4296
4297 val = (u64) bp->rx_pg_desc_mapping[0] >> 32;
4298 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
4299
4300 val = (u64) bp->rx_pg_desc_mapping[0] & 0xffffffff;
4301 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
4302
4303 if (CHIP_NUM(bp) == CHIP_NUM_5709)
4304 REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
4305 }
4221 4306
4222 val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; 4307 val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
4223 val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; 4308 val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
@@ -4230,6 +4315,15 @@ bnx2_init_rx_ring(struct bnx2 *bp)
4230 val = (u64) bp->rx_desc_mapping[0] & 0xffffffff; 4315 val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
4231 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); 4316 CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
4232 4317
4318 ring_prod = prod = bp->rx_pg_prod;
4319 for (i = 0; i < bp->rx_pg_ring_size; i++) {
4320 if (bnx2_alloc_rx_page(bp, ring_prod) < 0)
4321 break;
4322 prod = NEXT_RX_BD(prod);
4323 ring_prod = RX_PG_RING_IDX(prod);
4324 }
4325 bp->rx_pg_prod = prod;
4326
4233 ring_prod = prod = bp->rx_prod; 4327 ring_prod = prod = bp->rx_prod;
4234 for (i = 0; i < bp->rx_ring_size; i++) { 4328 for (i = 0; i < bp->rx_ring_size; i++) {
4235 if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) { 4329 if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
@@ -4240,6 +4334,7 @@ bnx2_init_rx_ring(struct bnx2 *bp)
4240 } 4334 }
4241 bp->rx_prod = prod; 4335 bp->rx_prod = prod;
4242 4336
4337 REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_PG_BDIDX, bp->rx_pg_prod);
4243 REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod); 4338 REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod);
4244 4339
4245 REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq); 4340 REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
@@ -4273,6 +4368,9 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
4273 rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8; 4368 rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
4274 4369
4275 bp->rx_copy_thresh = RX_COPY_THRESH; 4370 bp->rx_copy_thresh = RX_COPY_THRESH;
4371 bp->rx_pg_ring_size = 0;
4372 bp->rx_max_pg_ring = 0;
4373 bp->rx_max_pg_ring_idx = 0;
4276 4374
4277 bp->rx_buf_use_size = rx_size; 4375 bp->rx_buf_use_size = rx_size;
4278 /* hw alignment */ 4376 /* hw alignment */
@@ -4341,6 +4439,8 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
4341 4439
4342 dev_kfree_skb(skb); 4440 dev_kfree_skb(skb);
4343 } 4441 }
4442 for (i = 0; i < bp->rx_max_pg_ring_idx; i++)
4443 bnx2_free_rx_page(bp, i);
4344} 4444}
4345 4445
4346static void 4446static void
@@ -5813,11 +5913,11 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
5813 5913
5814 ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT; 5914 ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
5815 ering->rx_mini_max_pending = 0; 5915 ering->rx_mini_max_pending = 0;
5816 ering->rx_jumbo_max_pending = 0; 5916 ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
5817 5917
5818 ering->rx_pending = bp->rx_ring_size; 5918 ering->rx_pending = bp->rx_ring_size;
5819 ering->rx_mini_pending = 0; 5919 ering->rx_mini_pending = 0;
5820 ering->rx_jumbo_pending = 0; 5920 ering->rx_jumbo_pending = bp->rx_pg_ring_size;
5821 5921
5822 ering->tx_max_pending = MAX_TX_DESC_CNT; 5922 ering->tx_max_pending = MAX_TX_DESC_CNT;
5823 ering->tx_pending = bp->tx_ring_size; 5923 ering->tx_pending = bp->tx_ring_size;