diff options
author | Linas Vepstas <linas@austin.ibm.com> | 2006-12-13 16:06:59 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-05 16:58:43 -0500 |
commit | d4ed8f8d1fb7d59eb63d2eada9a32c2f8c3795e2 (patch) | |
tree | 5deb53b975439ce61e40bee57259c2d113df598a /drivers/net/spider_net.c | |
parent | 834324687d08e0f67b167934cb56406aa98ff8c6 (diff) |
Spidernet DMA coalescing
The current driver code performs 512 DMA mappings of a bunch of
32-byte ring descriptor structures. This is silly, as they are
all in contiguous memory. This patch changes the code to
dma_map_coherent() each rx/tx ring as a whole.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: James K Lewis <jklewis@us.ibm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/spider_net.c')
-rw-r--r-- | drivers/net/spider_net.c | 103 |
1 files changed, 47 insertions, 56 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 8ea2fc1b96cb..8c8381cbce0a 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -280,72 +280,67 @@ spider_net_free_chain(struct spider_net_card *card, | |||
280 | { | 280 | { |
281 | struct spider_net_descr *descr; | 281 | struct spider_net_descr *descr; |
282 | 282 | ||
283 | for (descr = chain->tail; !descr->bus_addr; descr = descr->next) { | 283 | descr = chain->ring; |
284 | pci_unmap_single(card->pdev, descr->bus_addr, | 284 | do { |
285 | SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
286 | descr->bus_addr = 0; | 285 | descr->bus_addr = 0; |
287 | } | 286 | descr->next_descr_addr = 0; |
287 | descr = descr->next; | ||
288 | } while (descr != chain->ring); | ||
289 | |||
290 | dma_free_coherent(&card->pdev->dev, chain->num_desc, | ||
291 | chain->ring, chain->dma_addr); | ||
288 | } | 292 | } |
289 | 293 | ||
290 | /** | 294 | /** |
291 | * spider_net_init_chain - links descriptor chain | 295 | * spider_net_init_chain - alloc and link descriptor chain |
292 | * @card: card structure | 296 | * @card: card structure |
293 | * @chain: address of chain | 297 | * @chain: address of chain |
294 | * @start_descr: address of descriptor array | ||
295 | * @no: number of descriptors | ||
296 | * | 298 | * |
297 | * we manage a circular list that mirrors the hardware structure, | 299 | * We manage a circular list that mirrors the hardware structure, |
298 | * except that the hardware uses bus addresses. | 300 | * except that the hardware uses bus addresses. |
299 | * | 301 | * |
300 | * returns 0 on success, <0 on failure | 302 | * Returns 0 on success, <0 on failure |
301 | */ | 303 | */ |
302 | static int | 304 | static int |
303 | spider_net_init_chain(struct spider_net_card *card, | 305 | spider_net_init_chain(struct spider_net_card *card, |
304 | struct spider_net_descr_chain *chain, | 306 | struct spider_net_descr_chain *chain) |
305 | struct spider_net_descr *start_descr, | ||
306 | int no) | ||
307 | { | 307 | { |
308 | int i; | 308 | int i; |
309 | struct spider_net_descr *descr; | 309 | struct spider_net_descr *descr; |
310 | dma_addr_t buf; | 310 | dma_addr_t buf; |
311 | size_t alloc_size; | ||
311 | 312 | ||
312 | descr = start_descr; | 313 | alloc_size = chain->num_desc * sizeof (struct spider_net_descr); |
313 | memset(descr, 0, sizeof(*descr) * no); | ||
314 | 314 | ||
315 | /* set up the hardware pointers in each descriptor */ | 315 | chain->ring = dma_alloc_coherent(&card->pdev->dev, alloc_size, |
316 | for (i=0; i<no; i++, descr++) { | 316 | &chain->dma_addr, GFP_KERNEL); |
317 | descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; | ||
318 | 317 | ||
319 | buf = pci_map_single(card->pdev, descr, | 318 | if (!chain->ring) |
320 | SPIDER_NET_DESCR_SIZE, | 319 | return -ENOMEM; |
321 | PCI_DMA_BIDIRECTIONAL); | ||
322 | 320 | ||
323 | if (pci_dma_mapping_error(buf)) | 321 | descr = chain->ring; |
324 | goto iommu_error; | 322 | memset(descr, 0, alloc_size); |
323 | |||
324 | /* Set up the hardware pointers in each descriptor */ | ||
325 | buf = chain->dma_addr; | ||
326 | for (i=0; i < chain->num_desc; i++, descr++) { | ||
327 | descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; | ||
325 | 328 | ||
326 | descr->bus_addr = buf; | 329 | descr->bus_addr = buf; |
330 | descr->next_descr_addr = 0; | ||
327 | descr->next = descr + 1; | 331 | descr->next = descr + 1; |
328 | descr->prev = descr - 1; | 332 | descr->prev = descr - 1; |
329 | 333 | ||
334 | buf += sizeof(struct spider_net_descr); | ||
330 | } | 335 | } |
331 | /* do actual circular list */ | 336 | /* do actual circular list */ |
332 | (descr-1)->next = start_descr; | 337 | (descr-1)->next = chain->ring; |
333 | start_descr->prev = descr-1; | 338 | chain->ring->prev = descr-1; |
334 | 339 | ||
335 | spin_lock_init(&chain->lock); | 340 | spin_lock_init(&chain->lock); |
336 | chain->head = start_descr; | 341 | chain->head = chain->ring; |
337 | chain->tail = start_descr; | 342 | chain->tail = chain->ring; |
338 | |||
339 | return 0; | 343 | return 0; |
340 | |||
341 | iommu_error: | ||
342 | descr = start_descr; | ||
343 | for (i=0; i < no; i++, descr++) | ||
344 | if (descr->bus_addr) | ||
345 | pci_unmap_single(card->pdev, descr->bus_addr, | ||
346 | SPIDER_NET_DESCR_SIZE, | ||
347 | PCI_DMA_BIDIRECTIONAL); | ||
348 | return -ENOMEM; | ||
349 | } | 344 | } |
350 | 345 | ||
351 | /** | 346 | /** |
@@ -707,7 +702,7 @@ spider_net_set_low_watermark(struct spider_net_card *card) | |||
707 | } | 702 | } |
708 | 703 | ||
709 | /* If TX queue is short, don't even bother with interrupts */ | 704 | /* If TX queue is short, don't even bother with interrupts */ |
710 | if (cnt < card->num_tx_desc/4) | 705 | if (cnt < card->tx_chain.num_desc/4) |
711 | return cnt; | 706 | return cnt; |
712 | 707 | ||
713 | /* Set low-watermark 3/4th's of the way into the queue. */ | 708 | /* Set low-watermark 3/4th's of the way into the queue. */ |
@@ -1652,26 +1647,25 @@ spider_net_open(struct net_device *netdev) | |||
1652 | { | 1647 | { |
1653 | struct spider_net_card *card = netdev_priv(netdev); | 1648 | struct spider_net_card *card = netdev_priv(netdev); |
1654 | struct spider_net_descr *descr; | 1649 | struct spider_net_descr *descr; |
1655 | int i, result; | 1650 | int result; |
1656 | 1651 | ||
1657 | result = -ENOMEM; | 1652 | result = spider_net_init_chain(card, &card->tx_chain); |
1658 | if (spider_net_init_chain(card, &card->tx_chain, card->descr, | 1653 | if (result) |
1659 | card->num_tx_desc)) | ||
1660 | goto alloc_tx_failed; | 1654 | goto alloc_tx_failed; |
1661 | |||
1662 | card->low_watermark = NULL; | 1655 | card->low_watermark = NULL; |
1663 | 1656 | ||
1664 | /* rx_chain is after tx_chain, so offset is descr + tx_count */ | 1657 | result = spider_net_init_chain(card, &card->rx_chain); |
1665 | if (spider_net_init_chain(card, &card->rx_chain, | 1658 | if (result) |
1666 | card->descr + card->num_tx_desc, | ||
1667 | card->num_rx_desc)) | ||
1668 | goto alloc_rx_failed; | 1659 | goto alloc_rx_failed; |
1669 | 1660 | ||
1670 | descr = card->rx_chain.head; | 1661 | /* Make a ring of of bus addresses */ |
1671 | for (i=0; i < card->num_rx_desc; i++, descr++) | 1662 | descr = card->rx_chain.ring; |
1663 | do { | ||
1672 | descr->next_descr_addr = descr->next->bus_addr; | 1664 | descr->next_descr_addr = descr->next->bus_addr; |
1665 | descr = descr->next; | ||
1666 | } while (descr != card->rx_chain.ring); | ||
1673 | 1667 | ||
1674 | /* allocate rx skbs */ | 1668 | /* Allocate rx skbs */ |
1675 | if (spider_net_alloc_rx_skbs(card)) | 1669 | if (spider_net_alloc_rx_skbs(card)) |
1676 | goto alloc_skbs_failed; | 1670 | goto alloc_skbs_failed; |
1677 | 1671 | ||
@@ -1924,6 +1918,7 @@ spider_net_stop(struct net_device *netdev) | |||
1924 | 1918 | ||
1925 | /* release chains */ | 1919 | /* release chains */ |
1926 | spider_net_release_tx_chain(card, 1); | 1920 | spider_net_release_tx_chain(card, 1); |
1921 | spider_net_free_rx_chain_contents(card); | ||
1927 | 1922 | ||
1928 | spider_net_free_rx_chain_contents(card); | 1923 | spider_net_free_rx_chain_contents(card); |
1929 | 1924 | ||
@@ -2057,8 +2052,8 @@ spider_net_setup_netdev(struct spider_net_card *card) | |||
2057 | 2052 | ||
2058 | card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; | 2053 | card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; |
2059 | 2054 | ||
2060 | card->num_tx_desc = tx_descriptors; | 2055 | card->tx_chain.num_desc = tx_descriptors; |
2061 | card->num_rx_desc = rx_descriptors; | 2056 | card->rx_chain.num_desc = rx_descriptors; |
2062 | 2057 | ||
2063 | spider_net_setup_netdev_ops(netdev); | 2058 | spider_net_setup_netdev_ops(netdev); |
2064 | 2059 | ||
@@ -2107,12 +2102,8 @@ spider_net_alloc_card(void) | |||
2107 | { | 2102 | { |
2108 | struct net_device *netdev; | 2103 | struct net_device *netdev; |
2109 | struct spider_net_card *card; | 2104 | struct spider_net_card *card; |
2110 | size_t alloc_size; | ||
2111 | 2105 | ||
2112 | alloc_size = sizeof (*card) + | 2106 | netdev = alloc_etherdev(sizeof(struct spider_net_card)); |
2113 | sizeof (struct spider_net_descr) * rx_descriptors + | ||
2114 | sizeof (struct spider_net_descr) * tx_descriptors; | ||
2115 | netdev = alloc_etherdev(alloc_size); | ||
2116 | if (!netdev) | 2107 | if (!netdev) |
2117 | return NULL; | 2108 | return NULL; |
2118 | 2109 | ||