aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-08-18 11:17:08 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-18 23:26:48 -0400
commitee5f68fea27b53b16c265b1f9ed8aa3bc9024c96 (patch)
treef24199e39c59f88516e0914faf74c26d991815a1 /drivers/net/sky2.c
parentc119731d6606ae25d787740d60706e2732454637 (diff)
sky2: dynamic size transmit ring
Allocate and size transmit ring based on parameters. Saves excess space and allows configuring larger rings for testing. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 58d35214d12d..7c1880d8b31f 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -64,10 +64,12 @@
64#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) 64#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2)
65#define RX_DEF_PENDING RX_MAX_PENDING 65#define RX_DEF_PENDING RX_MAX_PENDING
66 66
67#define TX_RING_SIZE 512 67/* This is the worst case number of transmit list elements for a single skb:
68#define TX_DEF_PENDING 128 68 VLAN + TSO + CKSUM + Data + skb_frags * DMA */
69#define MAX_SKB_TX_LE (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS) 69#define MAX_SKB_TX_LE (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS)
70#define TX_MIN_PENDING (MAX_SKB_TX_LE+1) 70#define TX_MIN_PENDING (MAX_SKB_TX_LE+1)
71#define TX_MAX_PENDING 4096
72#define TX_DEF_PENDING 127
71 73
72#define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */ 74#define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */
73#define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le)) 75#define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le))
@@ -1000,7 +1002,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot)
1000{ 1002{
1001 struct sky2_tx_le *le = sky2->tx_le + *slot; 1003 struct sky2_tx_le *le = sky2->tx_le + *slot;
1002 1004
1003 *slot = RING_NEXT(*slot, TX_RING_SIZE); 1005 *slot = RING_NEXT(*slot, sky2->tx_ring_size);
1004 le->ctrl = 0; 1006 le->ctrl = 0;
1005 return le; 1007 return le;
1006} 1008}
@@ -1433,13 +1435,13 @@ static int sky2_up(struct net_device *dev)
1433 1435
1434 /* must be power of 2 */ 1436 /* must be power of 2 */
1435 sky2->tx_le = pci_alloc_consistent(hw->pdev, 1437 sky2->tx_le = pci_alloc_consistent(hw->pdev,
1436 TX_RING_SIZE * 1438 sky2->tx_ring_size *
1437 sizeof(struct sky2_tx_le), 1439 sizeof(struct sky2_tx_le),
1438 &sky2->tx_le_map); 1440 &sky2->tx_le_map);
1439 if (!sky2->tx_le) 1441 if (!sky2->tx_le)
1440 goto err_out; 1442 goto err_out;
1441 1443
1442 sky2->tx_ring = kcalloc(TX_RING_SIZE, sizeof(struct tx_ring_info), 1444 sky2->tx_ring = kcalloc(sky2->tx_ring_size, sizeof(struct tx_ring_info),
1443 GFP_KERNEL); 1445 GFP_KERNEL);
1444 if (!sky2->tx_ring) 1446 if (!sky2->tx_ring)
1445 goto err_out; 1447 goto err_out;
@@ -1491,7 +1493,7 @@ static int sky2_up(struct net_device *dev)
1491 sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV); 1493 sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV);
1492 1494
1493 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, 1495 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
1494 TX_RING_SIZE - 1); 1496 sky2->tx_ring_size - 1);
1495 1497
1496#ifdef SKY2_VLAN_TAG_USED 1498#ifdef SKY2_VLAN_TAG_USED
1497 sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL); 1499 sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
@@ -1520,7 +1522,7 @@ err_out:
1520 } 1522 }
1521 if (sky2->tx_le) { 1523 if (sky2->tx_le) {
1522 pci_free_consistent(hw->pdev, 1524 pci_free_consistent(hw->pdev,
1523 TX_RING_SIZE * sizeof(struct sky2_tx_le), 1525 sky2->tx_ring_size * sizeof(struct sky2_tx_le),
1524 sky2->tx_le, sky2->tx_le_map); 1526 sky2->tx_le, sky2->tx_le_map);
1525 sky2->tx_le = NULL; 1527 sky2->tx_le = NULL;
1526 } 1528 }
@@ -1533,15 +1535,15 @@ err_out:
1533} 1535}
1534 1536
1535/* Modular subtraction in ring */ 1537/* Modular subtraction in ring */
1536static inline int tx_dist(unsigned tail, unsigned head) 1538static inline int tx_inuse(const struct sky2_port *sky2)
1537{ 1539{
1538 return (head - tail) & (TX_RING_SIZE - 1); 1540 return (sky2->tx_prod - sky2->tx_cons) & (sky2->tx_ring_size - 1);
1539} 1541}
1540 1542
1541/* Number of list elements available for next tx */ 1543/* Number of list elements available for next tx */
1542static inline int tx_avail(const struct sky2_port *sky2) 1544static inline int tx_avail(const struct sky2_port *sky2)
1543{ 1545{
1544 return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod); 1546 return sky2->tx_pending - tx_inuse(sky2);
1545} 1547}
1546 1548
1547/* Estimate of number of transmit list elements required */ 1549/* Estimate of number of transmit list elements required */
@@ -1717,7 +1719,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
1717 return NETDEV_TX_OK; 1719 return NETDEV_TX_OK;
1718 1720
1719mapping_unwind: 1721mapping_unwind:
1720 for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, TX_RING_SIZE)) { 1722 for (i = sky2->tx_prod; i != slot; i = RING_NEXT(i, sky2->tx_ring_size)) {
1721 le = sky2->tx_le + i; 1723 le = sky2->tx_le + i;
1722 re = sky2->tx_ring + i; 1724 re = sky2->tx_ring + i;
1723 1725
@@ -1760,10 +1762,10 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1760 struct pci_dev *pdev = sky2->hw->pdev; 1762 struct pci_dev *pdev = sky2->hw->pdev;
1761 unsigned idx; 1763 unsigned idx;
1762 1764
1763 BUG_ON(done >= TX_RING_SIZE); 1765 BUG_ON(done >= sky2->tx_ring_size);
1764 1766
1765 for (idx = sky2->tx_cons; idx != done; 1767 for (idx = sky2->tx_cons; idx != done;
1766 idx = RING_NEXT(idx, TX_RING_SIZE)) { 1768 idx = RING_NEXT(idx, sky2->tx_ring_size)) {
1767 struct sky2_tx_le *le = sky2->tx_le + idx; 1769 struct sky2_tx_le *le = sky2->tx_le + idx;
1768 struct tx_ring_info *re = sky2->tx_ring + idx; 1770 struct tx_ring_info *re = sky2->tx_ring + idx;
1769 1771
@@ -1799,7 +1801,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1799 else 1801 else
1800 dev_kfree_skb_any(skb); 1802 dev_kfree_skb_any(skb);
1801 1803
1802 sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); 1804 sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size);
1803 } 1805 }
1804 } 1806 }
1805 1807
@@ -1907,7 +1909,7 @@ static int sky2_down(struct net_device *dev)
1907 kfree(sky2->rx_ring); 1909 kfree(sky2->rx_ring);
1908 1910
1909 pci_free_consistent(hw->pdev, 1911 pci_free_consistent(hw->pdev,
1910 TX_RING_SIZE * sizeof(struct sky2_tx_le), 1912 sky2->tx_ring_size * sizeof(struct sky2_tx_le),
1911 sky2->tx_le, sky2->tx_le_map); 1913 sky2->tx_le, sky2->tx_le_map);
1912 kfree(sky2->tx_ring); 1914 kfree(sky2->tx_ring);
1913 1915
@@ -2517,7 +2519,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2517 2519
2518 case OP_TXINDEXLE: 2520 case OP_TXINDEXLE:
2519 /* TX index reports status for both ports */ 2521 /* TX index reports status for both ports */
2520 BUILD_BUG_ON(TX_RING_SIZE > 0x1000);
2521 sky2_tx_done(hw->dev[0], status & 0xfff); 2522 sky2_tx_done(hw->dev[0], status & 0xfff);
2522 if (hw->dev[1]) 2523 if (hw->dev[1])
2523 sky2_tx_done(hw->dev[1], 2524 sky2_tx_done(hw->dev[1],
@@ -3669,7 +3670,7 @@ static int sky2_set_coalesce(struct net_device *dev,
3669 ecmd->rx_coalesce_usecs_irq > tmax) 3670 ecmd->rx_coalesce_usecs_irq > tmax)
3670 return -EINVAL; 3671 return -EINVAL;
3671 3672
3672 if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1) 3673 if (ecmd->tx_max_coalesced_frames >= sky2->tx_ring_size-1)
3673 return -EINVAL; 3674 return -EINVAL;
3674 if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING) 3675 if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING)
3675 return -EINVAL; 3676 return -EINVAL;
@@ -3713,7 +3714,7 @@ static void sky2_get_ringparam(struct net_device *dev,
3713 ering->rx_max_pending = RX_MAX_PENDING; 3714 ering->rx_max_pending = RX_MAX_PENDING;
3714 ering->rx_mini_max_pending = 0; 3715 ering->rx_mini_max_pending = 0;
3715 ering->rx_jumbo_max_pending = 0; 3716 ering->rx_jumbo_max_pending = 0;
3716 ering->tx_max_pending = TX_RING_SIZE - 1; 3717 ering->tx_max_pending = TX_MAX_PENDING;
3717 3718
3718 ering->rx_pending = sky2->rx_pending; 3719 ering->rx_pending = sky2->rx_pending;
3719 ering->rx_mini_pending = 0; 3720 ering->rx_mini_pending = 0;
@@ -3728,14 +3729,15 @@ static int sky2_set_ringparam(struct net_device *dev,
3728 3729
3729 if (ering->rx_pending > RX_MAX_PENDING || 3730 if (ering->rx_pending > RX_MAX_PENDING ||
3730 ering->rx_pending < 8 || 3731 ering->rx_pending < 8 ||
3731 ering->tx_pending < MAX_SKB_TX_LE || 3732 ering->tx_pending < TX_MIN_PENDING ||
3732 ering->tx_pending > TX_RING_SIZE - 1) 3733 ering->tx_pending > TX_MAX_PENDING)
3733 return -EINVAL; 3734 return -EINVAL;
3734 3735
3735 sky2_detach(dev); 3736 sky2_detach(dev);
3736 3737
3737 sky2->rx_pending = ering->rx_pending; 3738 sky2->rx_pending = ering->rx_pending;
3738 sky2->tx_pending = ering->tx_pending; 3739 sky2->tx_pending = ering->tx_pending;
3740 sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1);
3739 3741
3740 return sky2_reattach(dev); 3742 return sky2_reattach(dev);
3741} 3743}
@@ -4105,8 +4107,8 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
4105 4107
4106 /* Dump contents of tx ring */ 4108 /* Dump contents of tx ring */
4107 sop = 1; 4109 sop = 1;
4108 for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE; 4110 for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < sky2->tx_ring_size;
4109 idx = RING_NEXT(idx, TX_RING_SIZE)) { 4111 idx = RING_NEXT(idx, sky2->tx_ring_size)) {
4110 const struct sky2_tx_le *le = sky2->tx_le + idx; 4112 const struct sky2_tx_le *le = sky2->tx_le + idx;
4111 u32 a = le32_to_cpu(le->addr); 4113 u32 a = le32_to_cpu(le->addr);
4112 4114
@@ -4315,7 +4317,9 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
4315 sky2->wol = wol; 4317 sky2->wol = wol;
4316 4318
4317 spin_lock_init(&sky2->phy_lock); 4319 spin_lock_init(&sky2->phy_lock);
4320
4318 sky2->tx_pending = TX_DEF_PENDING; 4321 sky2->tx_pending = TX_DEF_PENDING;
4322 sky2->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1);
4319 sky2->rx_pending = RX_DEF_PENDING; 4323 sky2->rx_pending = RX_DEF_PENDING;
4320 4324
4321 hw->dev[port] = dev; 4325 hw->dev[port] = dev;