diff options
author | Michael Chan <mchan@broadcom.com> | 2007-12-12 14:19:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:57:30 -0500 |
commit | 47bf4246a357d36762c9e7c282d7307152eb92e1 (patch) | |
tree | 91f28518be9daf3a2e26efd9efa9bdbb4b664454 /drivers/net/bnx2.c | |
parent | 110d0ef9907b519fed1607c73b3ae883f270561e (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.c | 104 |
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 | ||
488 | static int | 498 | static 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 | ||
2197 | static inline int | 2226 | static inline int |
2227 | bnx2_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 | |||
2246 | static void | ||
2247 | bnx2_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 | |||
2262 | static inline int | ||
2198 | bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) | 2263 | bnx2_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 | ||
4346 | static void | 4446 | static 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; |