diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/sky2.c | 63 |
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, | |||
| 690 | setnew: | 690 | setnew: |
| 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. */ | ||
| 727 | static 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 | ||
| 1621 | error: | 1616 | error: |
| @@ -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) | |||
| 1880 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | 1875 | static 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) |
