aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorshemminger@osdl.org <shemminger@osdl.org>2005-11-30 14:45:14 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-12-01 02:20:20 -0500
commit13210ce5c06ed9537558b85e9c0df4248b28f1f7 (patch)
tree8fd431a7f071818b82d156ce57604dfd9cc11ded /drivers/net/sky2.c
parent42eeea0145a1c7570624ddeaa15d3f357a52edf8 (diff)
[PATCH] sky2: improve receive performance
Changes to receive side processing: * bigger receive ring * clean up polling loop Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c66
1 files changed, 34 insertions, 32 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 83361aed49f6..e6f71c1232bc 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -72,10 +72,10 @@
72 unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \ 72 unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \
73 (hw)->chip_rev == CHIP_REV_YU_EC_A1) 73 (hw)->chip_rev == CHIP_REV_YU_EC_A1)
74 74
75#define RX_LE_SIZE 256 75#define RX_LE_SIZE 512
76#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) 76#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
77#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) 77#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
78#define RX_DEF_PENDING 128 78#define RX_DEF_PENDING RX_MAX_PENDING
79#define RX_COPY_THRESHOLD 256 79#define RX_COPY_THRESHOLD 256
80 80
81#define TX_RING_SIZE 512 81#define TX_RING_SIZE 512
@@ -1596,7 +1596,6 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
1596{ 1596{
1597 struct ring_info *re = sky2->rx_ring + sky2->rx_next; 1597 struct ring_info *re = sky2->rx_ring + sky2->rx_next;
1598 struct sk_buff *skb = NULL; 1598 struct sk_buff *skb = NULL;
1599 struct net_device *dev;
1600 const unsigned int bufsize = rx_size(sky2); 1599 const unsigned int bufsize = rx_size(sky2);
1601 1600
1602 if (unlikely(netif_msg_rx_status(sky2))) 1601 if (unlikely(netif_msg_rx_status(sky2)))
@@ -1643,11 +1642,6 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
1643 } 1642 }
1644 1643
1645 skb_put(skb, length); 1644 skb_put(skb, length);
1646 dev = sky2->netdev;
1647 skb->dev = dev;
1648 skb->protocol = eth_type_trans(skb, dev);
1649 dev->last_rx = jiffies;
1650
1651resubmit: 1645resubmit:
1652 re->skb->ip_summed = CHECKSUM_NONE; 1646 re->skb->ip_summed = CHECKSUM_NONE;
1653 sky2_rx_add(sky2, re); 1647 sky2_rx_add(sky2, re);
@@ -1702,35 +1696,42 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1702 BUG_ON(hwidx >= STATUS_RING_SIZE); 1696 BUG_ON(hwidx >= STATUS_RING_SIZE);
1703 rmb(); 1697 rmb();
1704 1698
1705 do { 1699 while (hwidx != hw->st_idx) {
1706 struct sky2_status_le *le = hw->st_le + hw->st_idx; 1700 struct sky2_status_le *le = hw->st_le + hw->st_idx;
1701 struct net_device *dev;
1707 struct sky2_port *sky2; 1702 struct sky2_port *sky2;
1708 struct sk_buff *skb; 1703 struct sk_buff *skb;
1709 u32 status; 1704 u32 status;
1710 u16 length; 1705 u16 length;
1706 u8 op;
1711 1707
1712 /* Are we done yet? */ 1708 le = hw->st_le + hw->st_idx;
1713 if (hw->st_idx == hwidx) {
1714 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
1715 hwidx = sky2_read16(hw, STAT_PUT_IDX);
1716 if (hwidx == hw->st_idx)
1717 break;
1718 }
1719
1720 hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; 1709 hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
1721 prefetch(&hw->st_le[hw->st_idx]); 1710 prefetch(hw->st_le + hw->st_idx);
1722 1711
1723 BUG_ON(le->link >= hw->ports || !hw->dev[le->link]); 1712 BUG_ON(le->link >= hw->ports || !hw->dev[le->link]);
1724 1713
1725 sky2 = netdev_priv(hw->dev[le->link]); 1714 BUG_ON(le->link >= 2);
1715 dev = hw->dev[le->link];
1716 if (dev == NULL || !netif_running(dev))
1717 continue;
1718
1719 sky2 = netdev_priv(dev);
1726 status = le32_to_cpu(le->status); 1720 status = le32_to_cpu(le->status);
1727 length = le16_to_cpu(le->length); 1721 length = le16_to_cpu(le->length);
1722 op = le->opcode & ~HW_OWNER;
1723 le->opcode = 0;
1728 1724
1729 switch (le->opcode & ~HW_OWNER) { 1725 switch (op) {
1730 case OP_RXSTAT: 1726 case OP_RXSTAT:
1731 skb = sky2_receive(sky2, length, status); 1727 skb = sky2_receive(sky2, length, status);
1732 if (!skb) 1728 if (!skb)
1733 break; 1729 break;
1730
1731 skb->dev = dev;
1732 skb->protocol = eth_type_trans(skb, dev);
1733 dev->last_rx = jiffies;
1734
1734#ifdef SKY2_VLAN_TAG_USED 1735#ifdef SKY2_VLAN_TAG_USED
1735 if (sky2->vlgrp && (status & GMR_FS_VLAN)) { 1736 if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
1736 vlan_hwaccel_receive_skb(skb, 1737 vlan_hwaccel_receive_skb(skb,
@@ -1739,7 +1740,9 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1739 } else 1740 } else
1740#endif 1741#endif
1741 netif_receive_skb(skb); 1742 netif_receive_skb(skb);
1742 ++work_done; 1743
1744 if (++work_done >= to_do)
1745 goto exit_loop;
1743 break; 1746 break;
1744 1747
1745#ifdef SKY2_VLAN_TAG_USED 1748#ifdef SKY2_VLAN_TAG_USED
@@ -1765,18 +1768,15 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1765 default: 1768 default:
1766 if (net_ratelimit()) 1769 if (net_ratelimit())
1767 printk(KERN_WARNING PFX 1770 printk(KERN_WARNING PFX
1768 "unknown status opcode 0x%x\n", 1771 "unknown status opcode 0x%x\n", op);
1769 le->opcode);
1770 break; 1772 break;
1771 } 1773 }
1774 }
1772 1775
1773 le->opcode = 0; /* paranoia */ 1776exit_loop:
1774 } while (work_done < to_do);
1775 1777
1776 mmiowb(); 1778 mmiowb();
1777 1779
1778 *budget -= work_done;
1779 dev0->quota -= work_done;
1780 if (work_done < to_do) { 1780 if (work_done < to_do) {
1781 /* 1781 /*
1782 * Another chip workaround, need to restart TX timer if status 1782 * Another chip workaround, need to restart TX timer if status
@@ -1790,11 +1790,13 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1790 netif_rx_complete(dev0); 1790 netif_rx_complete(dev0);
1791 hw->intr_mask |= Y2_IS_STAT_BMU; 1791 hw->intr_mask |= Y2_IS_STAT_BMU;
1792 sky2_write32(hw, B0_IMSK, hw->intr_mask); 1792 sky2_write32(hw, B0_IMSK, hw->intr_mask);
1793 sky2_read32(hw, B0_IMSK); 1793 mmiowb();
1794 return 0;
1795 } else {
1796 *budget -= work_done;
1797 dev0->quota -= work_done;
1798 return 1;
1794 } 1799 }
1795
1796 return work_done >= to_do;
1797
1798} 1800}
1799 1801
1800static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) 1802static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)