aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 92d69fff8755..a85a8d16908f 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -76,7 +76,7 @@
76 76
77#define RX_LE_SIZE 256 77#define RX_LE_SIZE 256
78#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) 78#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
79#define RX_MAX_PENDING (RX_LE_SIZE/2 - 1) 79#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
80#define RX_DEF_PENDING 128 80#define RX_DEF_PENDING 128
81#define RX_COPY_THRESHOLD 256 81#define RX_COPY_THRESHOLD 256
82 82
@@ -690,7 +690,7 @@ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q,
690setnew: 690setnew:
691 sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); 691 sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
692 } 692 }
693 *last = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX)); 693 *last = idx;
694} 694}
695 695
696 696
@@ -723,15 +723,6 @@ static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re)
723 le->opcode = OP_PACKET | HW_OWNER; 723 le->opcode = OP_PACKET | HW_OWNER;
724} 724}
725 725
726/* Tell receiver about new buffers. */
727static inline void rx_set_put(struct net_device *dev)
728{
729 struct sky2_port *sky2 = netdev_priv(dev);
730
731 if (sky2->rx_last_put != sky2->rx_put)
732 sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put,
733 &sky2->rx_last_put, RX_LE_SIZE);
734}
735 726
736/* Tell chip where to start receive checksum. 727/* Tell chip where to start receive checksum.
737 * Actually has two checksums, but set both same to avoid possible byte 728 * Actually has two checksums, but set both same to avoid possible byte
@@ -1616,6 +1607,10 @@ resubmit:
1616 re->skb->ip_summed = CHECKSUM_NONE; 1607 re->skb->ip_summed = CHECKSUM_NONE;
1617 sky2_rx_add(sky2, re); 1608 sky2_rx_add(sky2, re);
1618 1609
1610 /* Tell receiver about new buffers. */
1611 sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put,
1612 &sky2->rx_last_put, RX_LE_SIZE);
1613
1619 return skb; 1614 return skb;
1620 1615
1621error: 1616error:
@@ -1664,16 +1659,26 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1664 hwidx = sky2_read16(hw, STAT_PUT_IDX); 1659 hwidx = sky2_read16(hw, STAT_PUT_IDX);
1665 BUG_ON(hwidx >= STATUS_RING_SIZE); 1660 BUG_ON(hwidx >= STATUS_RING_SIZE);
1666 rmb(); 1661 rmb();
1667 while (hw->st_idx != hwidx && work_done < to_do) { 1662
1663 do {
1668 struct sky2_status_le *le = hw->st_le + hw->st_idx; 1664 struct sky2_status_le *le = hw->st_le + hw->st_idx;
1669 struct sky2_port *sky2; 1665 struct sky2_port *sky2;
1670 struct sk_buff *skb; 1666 struct sk_buff *skb;
1671 u32 status; 1667 u32 status;
1672 u16 length; 1668 u16 length;
1673 1669
1674 BUG_ON(le->link >= hw->ports); 1670 /* Are we done yet? */
1675 if (!hw->dev[le->link]) 1671 if (hw->st_idx == hwidx) {
1676 goto skip; 1672 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
1673 hwidx = sky2_read16(hw, STAT_PUT_IDX);
1674 if (hwidx == hw->st_idx)
1675 break;
1676 }
1677
1678 hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
1679 prefetch(&hw->st_le[hw->st_idx]);
1680
1681 BUG_ON(le->link >= hw->ports || !hw->dev[le->link]);
1677 1682
1678 sky2 = netdev_priv(hw->dev[le->link]); 1683 sky2 = netdev_priv(hw->dev[le->link]);
1679 status = le32_to_cpu(le->status); 1684 status = le32_to_cpu(le->status);
@@ -1692,6 +1697,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1692 } else 1697 } else
1693#endif 1698#endif
1694 netif_receive_skb(skb); 1699 netif_receive_skb(skb);
1700 ++work_done;
1695 break; 1701 break;
1696 1702
1697#ifdef SKY2_VLAN_TAG_USED 1703#ifdef SKY2_VLAN_TAG_USED
@@ -1722,22 +1728,11 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1722 break; 1728 break;
1723 } 1729 }
1724 1730
1725 skip: 1731 le->opcode = 0; /* paranoia */
1726 hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; 1732 } while (work_done < to_do);
1727 if (hw->st_idx == hwidx) {
1728 hwidx = sky2_read16(hw, STAT_PUT_IDX);
1729 rmb();
1730 }
1731 }
1732 1733
1733 mmiowb(); 1734 mmiowb();
1734 1735
1735 if (hw->dev[0])
1736 rx_set_put(hw->dev[0]);
1737
1738 if (hw->dev[1])
1739 rx_set_put(hw->dev[1]);
1740
1741 *budget -= work_done; 1736 *budget -= work_done;
1742 dev0->quota -= work_done; 1737 dev0->quota -= work_done;
1743 if (work_done < to_do) { 1738 if (work_done < to_do) {
@@ -1750,10 +1745,10 @@ static int sky2_poll(struct net_device *dev0, int *budget)
1750 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); 1745 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
1751 } 1746 }
1752 1747
1748 netif_rx_complete(dev0);
1753 hw->intr_mask |= Y2_IS_STAT_BMU; 1749 hw->intr_mask |= Y2_IS_STAT_BMU;
1754 sky2_write32(hw, B0_IMSK, hw->intr_mask); 1750 sky2_write32(hw, B0_IMSK, hw->intr_mask);
1755 sky2_read32(hw, B0_IMSK); 1751 sky2_read32(hw, B0_IMSK);
1756 netif_rx_complete(dev0);
1757 } 1752 }
1758 1753
1759 return work_done >= to_do; 1754 return work_done >= to_do;
@@ -1880,6 +1875,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
1880static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) 1875static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
1881{ 1876{
1882 struct sky2_hw *hw = dev_id; 1877 struct sky2_hw *hw = dev_id;
1878 struct net_device *dev0 = hw->dev[0];
1883 u32 status; 1879 u32 status;
1884 1880
1885 status = sky2_read32(hw, B0_Y2_SP_ISRC2); 1881 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
@@ -1890,12 +1886,13 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
1890 sky2_hw_intr(hw); 1886 sky2_hw_intr(hw);
1891 1887
1892 /* Do NAPI for Rx and Tx status */ 1888 /* Do NAPI for Rx and Tx status */
1893 if ((status & Y2_IS_STAT_BMU) && netif_rx_schedule_test(hw->dev[0])) { 1889 if (status & Y2_IS_STAT_BMU) {
1894 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
1895
1896 hw->intr_mask &= ~Y2_IS_STAT_BMU; 1890 hw->intr_mask &= ~Y2_IS_STAT_BMU;
1897 sky2_write32(hw, B0_IMSK, hw->intr_mask); 1891 sky2_write32(hw, B0_IMSK, hw->intr_mask);
1898 __netif_rx_schedule(hw->dev[0]); 1892 prefetch(&hw->st_le[hw->st_idx]);
1893
1894 if (netif_rx_schedule_test(dev0))
1895 __netif_rx_schedule(dev0);
1899 } 1896 }
1900 1897
1901 if (status & Y2_IS_IRQ_PHY1) 1898 if (status & Y2_IS_IRQ_PHY1)