diff options
author | Brice Goglin <brice@myri.com> | 2006-12-11 05:25:42 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-11 09:54:06 -0500 |
commit | c7dab99b080accb2751c96bf66cd5ab12c78f8e4 (patch) | |
tree | e8d290ede4fe7b2ce85b5d36c0d644353179fc0e /drivers/net/myri10ge | |
parent | dd50f3361f9f0bb407658e9087947c9bdcdefffc (diff) |
[PATCH] myri10ge: switch to page-based skb
Switch to physical page skb, by calling the new page-based
allocation routines and using myri10ge_page_rx_done().
Signed-off-by: Brice Goglin <brice@myri.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/myri10ge')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 172 |
1 files changed, 93 insertions, 79 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 05b4f93518f5..4d2be9c59164 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -1264,13 +1264,13 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) | |||
1264 | rx_done->entry[idx].length = 0; | 1264 | rx_done->entry[idx].length = 0; |
1265 | checksum = csum_unfold(rx_done->entry[idx].checksum); | 1265 | checksum = csum_unfold(rx_done->entry[idx].checksum); |
1266 | if (length <= mgp->small_bytes) | 1266 | if (length <= mgp->small_bytes) |
1267 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, | 1267 | rx_ok = myri10ge_page_rx_done(mgp, &mgp->rx_small, |
1268 | mgp->small_bytes, | 1268 | mgp->small_bytes, |
1269 | length, checksum); | 1269 | length, checksum); |
1270 | else | 1270 | else |
1271 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, | 1271 | rx_ok = myri10ge_page_rx_done(mgp, &mgp->rx_big, |
1272 | mgp->dev->mtu + ETH_HLEN, | 1272 | mgp->big_bytes, |
1273 | length, checksum); | 1273 | length, checksum); |
1274 | rx_packets += rx_ok; | 1274 | rx_packets += rx_ok; |
1275 | rx_bytes += rx_ok * (unsigned long)length; | 1275 | rx_bytes += rx_ok * (unsigned long)length; |
1276 | cnt++; | 1276 | cnt++; |
@@ -1284,6 +1284,14 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) | |||
1284 | rx_done->cnt = cnt; | 1284 | rx_done->cnt = cnt; |
1285 | mgp->stats.rx_packets += rx_packets; | 1285 | mgp->stats.rx_packets += rx_packets; |
1286 | mgp->stats.rx_bytes += rx_bytes; | 1286 | mgp->stats.rx_bytes += rx_bytes; |
1287 | |||
1288 | /* restock receive rings if needed */ | ||
1289 | if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) | ||
1290 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
1291 | mgp->small_bytes + MXGEFW_PAD, 0); | ||
1292 | if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) | ||
1293 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); | ||
1294 | |||
1287 | } | 1295 | } |
1288 | 1296 | ||
1289 | static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) | 1297 | static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) |
@@ -1674,56 +1682,48 @@ static int myri10ge_allocate_rings(struct net_device *dev) | |||
1674 | goto abort_with_rx_small_info; | 1682 | goto abort_with_rx_small_info; |
1675 | 1683 | ||
1676 | /* Fill the receive rings */ | 1684 | /* Fill the receive rings */ |
1685 | mgp->rx_big.cnt = 0; | ||
1686 | mgp->rx_small.cnt = 0; | ||
1687 | mgp->rx_big.fill_cnt = 0; | ||
1688 | mgp->rx_small.fill_cnt = 0; | ||
1689 | mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE; | ||
1690 | mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; | ||
1691 | mgp->rx_small.watchdog_needed = 0; | ||
1692 | mgp->rx_big.watchdog_needed = 0; | ||
1693 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
1694 | mgp->small_bytes + MXGEFW_PAD, 0); | ||
1677 | 1695 | ||
1678 | for (i = 0; i <= mgp->rx_small.mask; i++) { | 1696 | if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) { |
1679 | status = myri10ge_getbuf(&mgp->rx_small, mgp, | 1697 | printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n", |
1680 | mgp->small_bytes, i); | 1698 | dev->name, mgp->rx_small.fill_cnt); |
1681 | if (status) { | 1699 | goto abort_with_rx_small_ring; |
1682 | printk(KERN_ERR | ||
1683 | "myri10ge: %s: alloced only %d small bufs\n", | ||
1684 | dev->name, i); | ||
1685 | goto abort_with_rx_small_ring; | ||
1686 | } | ||
1687 | } | 1700 | } |
1688 | 1701 | ||
1689 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1702 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); |
1690 | status = | 1703 | if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) { |
1691 | myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i); | 1704 | printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n", |
1692 | if (status) { | 1705 | dev->name, mgp->rx_big.fill_cnt); |
1693 | printk(KERN_ERR | 1706 | goto abort_with_rx_big_ring; |
1694 | "myri10ge: %s: alloced only %d big bufs\n", | ||
1695 | dev->name, i); | ||
1696 | goto abort_with_rx_big_ring; | ||
1697 | } | ||
1698 | } | 1707 | } |
1699 | 1708 | ||
1700 | return 0; | 1709 | return 0; |
1701 | 1710 | ||
1702 | abort_with_rx_big_ring: | 1711 | abort_with_rx_big_ring: |
1703 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1712 | for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { |
1704 | if (mgp->rx_big.info[i].skb != NULL) | 1713 | int idx = i & mgp->rx_big.mask; |
1705 | dev_kfree_skb_any(mgp->rx_big.info[i].skb); | 1714 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], |
1706 | if (pci_unmap_len(&mgp->rx_big.info[i], len)) | 1715 | mgp->big_bytes); |
1707 | pci_unmap_single(mgp->pdev, | 1716 | put_page(mgp->rx_big.info[idx].page); |
1708 | pci_unmap_addr(&mgp->rx_big.info[i], | ||
1709 | bus), | ||
1710 | pci_unmap_len(&mgp->rx_big.info[i], | ||
1711 | len), | ||
1712 | PCI_DMA_FROMDEVICE); | ||
1713 | } | 1717 | } |
1714 | 1718 | ||
1715 | abort_with_rx_small_ring: | 1719 | abort_with_rx_small_ring: |
1716 | for (i = 0; i <= mgp->rx_small.mask; i++) { | 1720 | for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { |
1717 | if (mgp->rx_small.info[i].skb != NULL) | 1721 | int idx = i & mgp->rx_small.mask; |
1718 | dev_kfree_skb_any(mgp->rx_small.info[i].skb); | 1722 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], |
1719 | if (pci_unmap_len(&mgp->rx_small.info[i], len)) | 1723 | mgp->small_bytes + MXGEFW_PAD); |
1720 | pci_unmap_single(mgp->pdev, | 1724 | put_page(mgp->rx_small.info[idx].page); |
1721 | pci_unmap_addr(&mgp->rx_small.info[i], | ||
1722 | bus), | ||
1723 | pci_unmap_len(&mgp->rx_small.info[i], | ||
1724 | len), | ||
1725 | PCI_DMA_FROMDEVICE); | ||
1726 | } | 1725 | } |
1726 | |||
1727 | kfree(mgp->rx_big.info); | 1727 | kfree(mgp->rx_big.info); |
1728 | 1728 | ||
1729 | abort_with_rx_small_info: | 1729 | abort_with_rx_small_info: |
@@ -1756,30 +1756,24 @@ static void myri10ge_free_rings(struct net_device *dev) | |||
1756 | 1756 | ||
1757 | mgp = netdev_priv(dev); | 1757 | mgp = netdev_priv(dev); |
1758 | 1758 | ||
1759 | for (i = 0; i <= mgp->rx_big.mask; i++) { | 1759 | for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { |
1760 | if (mgp->rx_big.info[i].skb != NULL) | 1760 | idx = i & mgp->rx_big.mask; |
1761 | dev_kfree_skb_any(mgp->rx_big.info[i].skb); | 1761 | if (i == mgp->rx_big.fill_cnt - 1) |
1762 | if (pci_unmap_len(&mgp->rx_big.info[i], len)) | 1762 | mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; |
1763 | pci_unmap_single(mgp->pdev, | 1763 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], |
1764 | pci_unmap_addr(&mgp->rx_big.info[i], | 1764 | mgp->big_bytes); |
1765 | bus), | 1765 | put_page(mgp->rx_big.info[idx].page); |
1766 | pci_unmap_len(&mgp->rx_big.info[i], | ||
1767 | len), | ||
1768 | PCI_DMA_FROMDEVICE); | ||
1769 | } | ||
1770 | |||
1771 | for (i = 0; i <= mgp->rx_small.mask; i++) { | ||
1772 | if (mgp->rx_small.info[i].skb != NULL) | ||
1773 | dev_kfree_skb_any(mgp->rx_small.info[i].skb); | ||
1774 | if (pci_unmap_len(&mgp->rx_small.info[i], len)) | ||
1775 | pci_unmap_single(mgp->pdev, | ||
1776 | pci_unmap_addr(&mgp->rx_small.info[i], | ||
1777 | bus), | ||
1778 | pci_unmap_len(&mgp->rx_small.info[i], | ||
1779 | len), | ||
1780 | PCI_DMA_FROMDEVICE); | ||
1781 | } | 1766 | } |
1782 | 1767 | ||
1768 | for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { | ||
1769 | idx = i & mgp->rx_small.mask; | ||
1770 | if (i == mgp->rx_small.fill_cnt - 1) | ||
1771 | mgp->rx_small.info[idx].page_offset = | ||
1772 | MYRI10GE_ALLOC_SIZE; | ||
1773 | myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], | ||
1774 | mgp->small_bytes + MXGEFW_PAD); | ||
1775 | put_page(mgp->rx_small.info[idx].page); | ||
1776 | } | ||
1783 | tx = &mgp->tx; | 1777 | tx = &mgp->tx; |
1784 | while (tx->done != tx->req) { | 1778 | while (tx->done != tx->req) { |
1785 | idx = tx->done & tx->mask; | 1779 | idx = tx->done & tx->mask; |
@@ -1847,19 +1841,18 @@ static int myri10ge_open(struct net_device *dev) | |||
1847 | */ | 1841 | */ |
1848 | 1842 | ||
1849 | if (dev->mtu <= ETH_DATA_LEN) | 1843 | if (dev->mtu <= ETH_DATA_LEN) |
1850 | mgp->small_bytes = 128; /* enough for a TCP header */ | 1844 | /* enough for a TCP header */ |
1845 | mgp->small_bytes = (128 > SMP_CACHE_BYTES) | ||
1846 | ? (128 - MXGEFW_PAD) | ||
1847 | : (SMP_CACHE_BYTES - MXGEFW_PAD); | ||
1851 | else | 1848 | else |
1852 | mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */ | 1849 | /* enough for an ETH_DATA_LEN frame */ |
1850 | mgp->small_bytes = ETH_FRAME_LEN; | ||
1853 | 1851 | ||
1854 | /* Override the small buffer size? */ | 1852 | /* Override the small buffer size? */ |
1855 | if (myri10ge_small_bytes > 0) | 1853 | if (myri10ge_small_bytes > 0) |
1856 | mgp->small_bytes = myri10ge_small_bytes; | 1854 | mgp->small_bytes = myri10ge_small_bytes; |
1857 | 1855 | ||
1858 | /* If the user sets an obscenely small MTU, adjust the small | ||
1859 | * bytes down to nearly nothing */ | ||
1860 | if (mgp->small_bytes >= (dev->mtu + ETH_HLEN)) | ||
1861 | mgp->small_bytes = 64; | ||
1862 | |||
1863 | /* get the lanai pointers to the send and receive rings */ | 1856 | /* get the lanai pointers to the send and receive rings */ |
1864 | 1857 | ||
1865 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); | 1858 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); |
@@ -1895,17 +1888,23 @@ static int myri10ge_open(struct net_device *dev) | |||
1895 | mgp->rx_big.wc_fifo = NULL; | 1888 | mgp->rx_big.wc_fifo = NULL; |
1896 | } | 1889 | } |
1897 | 1890 | ||
1898 | status = myri10ge_allocate_rings(dev); | ||
1899 | if (status != 0) | ||
1900 | goto abort_with_nothing; | ||
1901 | |||
1902 | /* Firmware needs the big buff size as a power of 2. Lie and | 1891 | /* Firmware needs the big buff size as a power of 2. Lie and |
1903 | * tell him the buffer is larger, because we only use 1 | 1892 | * tell him the buffer is larger, because we only use 1 |
1904 | * buffer/pkt, and the mtu will prevent overruns. | 1893 | * buffer/pkt, and the mtu will prevent overruns. |
1905 | */ | 1894 | */ |
1906 | big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; | 1895 | big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; |
1907 | while ((big_pow2 & (big_pow2 - 1)) != 0) | 1896 | if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) { |
1908 | big_pow2++; | 1897 | while ((big_pow2 & (big_pow2 - 1)) != 0) |
1898 | big_pow2++; | ||
1899 | mgp->big_bytes = dev->mtu + ETH_HLEN + MXGEFW_PAD; | ||
1900 | } else { | ||
1901 | big_pow2 = MYRI10GE_ALLOC_SIZE; | ||
1902 | mgp->big_bytes = big_pow2; | ||
1903 | } | ||
1904 | |||
1905 | status = myri10ge_allocate_rings(dev); | ||
1906 | if (status != 0) | ||
1907 | goto abort_with_nothing; | ||
1909 | 1908 | ||
1910 | /* now give firmware buffers sizes, and MTU */ | 1909 | /* now give firmware buffers sizes, and MTU */ |
1911 | cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; | 1910 | cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; |
@@ -2888,6 +2887,21 @@ static void myri10ge_watchdog_timer(unsigned long arg) | |||
2888 | struct myri10ge_priv *mgp; | 2887 | struct myri10ge_priv *mgp; |
2889 | 2888 | ||
2890 | mgp = (struct myri10ge_priv *)arg; | 2889 | mgp = (struct myri10ge_priv *)arg; |
2890 | |||
2891 | if (mgp->rx_small.watchdog_needed) { | ||
2892 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, | ||
2893 | mgp->small_bytes + MXGEFW_PAD, 1); | ||
2894 | if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >= | ||
2895 | myri10ge_fill_thresh) | ||
2896 | mgp->rx_small.watchdog_needed = 0; | ||
2897 | } | ||
2898 | if (mgp->rx_big.watchdog_needed) { | ||
2899 | myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1); | ||
2900 | if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >= | ||
2901 | myri10ge_fill_thresh) | ||
2902 | mgp->rx_big.watchdog_needed = 0; | ||
2903 | } | ||
2904 | |||
2891 | if (mgp->tx.req != mgp->tx.done && | 2905 | if (mgp->tx.req != mgp->tx.done && |
2892 | mgp->tx.done == mgp->watchdog_tx_done && | 2906 | mgp->tx.done == mgp->watchdog_tx_done && |
2893 | mgp->watchdog_tx_req != mgp->watchdog_tx_done) | 2907 | mgp->watchdog_tx_req != mgp->watchdog_tx_done) |