diff options
author | shemminger@osdl.org <shemminger@osdl.org> | 2005-11-30 14:45:14 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-12-01 02:20:20 -0500 |
commit | 13210ce5c06ed9537558b85e9c0df4248b28f1f7 (patch) | |
tree | 8fd431a7f071818b82d156ce57604dfd9cc11ded | |
parent | 42eeea0145a1c7570624ddeaa15d3f357a52edf8 (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>
-rw-r--r-- | drivers/net/sky2.c | 66 |
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 | |||
1651 | resubmit: | 1645 | resubmit: |
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 */ | 1776 | exit_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 | ||
1800 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) | 1802 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) |