diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 68f9c206a620..227df9876a2c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.1" | 54 | #define DRV_VERSION "1.2" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -99,8 +99,6 @@ MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | |||
99 | static const struct pci_device_id sky2_id_table[] = { | 99 | static const struct pci_device_id sky2_id_table[] = { |
100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
102 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, | ||
103 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, | ||
104 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | 102 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, |
105 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | 103 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, |
106 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | 104 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, |
@@ -579,8 +577,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
579 | reg = gma_read16(hw, port, GM_PHY_ADDR); | 577 | reg = gma_read16(hw, port, GM_PHY_ADDR); |
580 | gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); | 578 | gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); |
581 | 579 | ||
582 | for (i = 0; i < GM_MIB_CNT_SIZE; i++) | 580 | for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4) |
583 | gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i); | 581 | gma_read16(hw, port, i); |
584 | gma_write16(hw, port, GM_PHY_ADDR, reg); | 582 | gma_write16(hw, port, GM_PHY_ADDR, reg); |
585 | 583 | ||
586 | /* transmit control */ | 584 | /* transmit control */ |
@@ -927,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
927 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
928 | if (likely(skb)) { | 926 | if (likely(skb)) { |
929 | unsigned long p = (unsigned long) skb->data; | 927 | unsigned long p = (unsigned long) skb->data; |
930 | skb_reserve(skb, | 928 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
931 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
932 | } | 929 | } |
933 | 930 | ||
934 | return skb; | 931 | return skb; |
@@ -1688,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1688 | } | 1685 | } |
1689 | 1686 | ||
1690 | 1687 | ||
1691 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
1692 | /* Want receive buffer size to be multiple of 64 bits | 1688 | /* Want receive buffer size to be multiple of 64 bits |
1693 | * and incl room for vlan and truncation | 1689 | * and incl room for vlan and truncation |
1694 | */ | 1690 | */ |
1695 | static inline unsigned sky2_buf_size(int mtu) | 1691 | static inline unsigned sky2_buf_size(int mtu) |
1696 | { | 1692 | { |
1697 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1693 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1698 | } | 1694 | } |
1699 | 1695 | ||
1700 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1696 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -2088,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2088 | } | 2084 | } |
2089 | } | 2085 | } |
2090 | 2086 | ||
2087 | /* If idle then force a fake soft NAPI poll once a second | ||
2088 | * to work around cases where sharing an edge triggered interrupt. | ||
2089 | */ | ||
2090 | static void sky2_idle(unsigned long arg) | ||
2091 | { | ||
2092 | struct net_device *dev = (struct net_device *) arg; | ||
2093 | |||
2094 | local_irq_disable(); | ||
2095 | if (__netif_rx_schedule_prep(dev)) | ||
2096 | __netif_rx_schedule(dev); | ||
2097 | local_irq_enable(); | ||
2098 | } | ||
2099 | |||
2100 | |||
2091 | static int sky2_poll(struct net_device *dev0, int *budget) | 2101 | static int sky2_poll(struct net_device *dev0, int *budget) |
2092 | { | 2102 | { |
2093 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2103 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
@@ -2095,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2095 | int work_done = 0; | 2105 | int work_done = 0; |
2096 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2097 | 2107 | ||
2108 | restart_poll: | ||
2098 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
2099 | if (status & Y2_IS_HW_ERR) | 2110 | if (status & Y2_IS_HW_ERR) |
2100 | sky2_hw_intr(hw); | 2111 | sky2_hw_intr(hw); |
@@ -2125,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2125 | } | 2136 | } |
2126 | 2137 | ||
2127 | if (status & Y2_IS_STAT_BMU) { | 2138 | if (status & Y2_IS_STAT_BMU) { |
2128 | work_done = sky2_status_intr(hw, work_limit); | 2139 | work_done += sky2_status_intr(hw, work_limit - work_done); |
2129 | *budget -= work_done; | 2140 | *budget -= work_done; |
2130 | dev0->quota -= work_done; | 2141 | dev0->quota -= work_done; |
2131 | 2142 | ||
@@ -2135,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2135 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2136 | } | 2147 | } |
2137 | 2148 | ||
2138 | netif_rx_complete(dev0); | 2149 | mod_timer(&hw->idle_timer, jiffies + HZ); |
2150 | |||
2151 | local_irq_disable(); | ||
2152 | __netif_rx_complete(dev0); | ||
2139 | 2153 | ||
2140 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2154 | status = sky2_read32(hw, B0_Y2_SP_LISR); |
2155 | |||
2156 | if (unlikely(status)) { | ||
2157 | /* More work pending, try and keep going */ | ||
2158 | if (__netif_rx_schedule_prep(dev0)) { | ||
2159 | __netif_rx_reschedule(dev0, work_done); | ||
2160 | status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2161 | local_irq_enable(); | ||
2162 | goto restart_poll; | ||
2163 | } | ||
2164 | } | ||
2165 | |||
2166 | local_irq_enable(); | ||
2141 | return 0; | 2167 | return 0; |
2142 | } | 2168 | } |
2143 | 2169 | ||
@@ -2155,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2155 | prefetch(&hw->st_le[hw->st_idx]); | 2181 | prefetch(&hw->st_le[hw->st_idx]); |
2156 | if (likely(__netif_rx_schedule_prep(dev0))) | 2182 | if (likely(__netif_rx_schedule_prep(dev0))) |
2157 | __netif_rx_schedule(dev0); | 2183 | __netif_rx_schedule(dev0); |
2158 | else | ||
2159 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2160 | 2184 | ||
2161 | return IRQ_HANDLED; | 2185 | return IRQ_HANDLED; |
2162 | } | 2186 | } |
@@ -2195,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2195 | } | 2219 | } |
2196 | 2220 | ||
2197 | 2221 | ||
2198 | static int sky2_reset(struct sky2_hw *hw) | 2222 | static int __devinit sky2_reset(struct sky2_hw *hw) |
2199 | { | 2223 | { |
2200 | u16 status; | 2224 | u16 status; |
2201 | u8 t8, pmd_type; | 2225 | u8 t8, pmd_type; |
@@ -3278,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3278 | 3302 | ||
3279 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3280 | 3304 | ||
3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
3306 | |||
3281 | pci_set_drvdata(pdev, hw); | 3307 | pci_set_drvdata(pdev, hw); |
3282 | 3308 | ||
3283 | return 0; | 3309 | return 0; |
@@ -3313,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3313 | if (!hw) | 3339 | if (!hw) |
3314 | return; | 3340 | return; |
3315 | 3341 | ||
3342 | del_timer_sync(&hw->idle_timer); | ||
3343 | |||
3344 | sky2_write32(hw, B0_IMSK, 0); | ||
3316 | dev0 = hw->dev[0]; | 3345 | dev0 = hw->dev[0]; |
3317 | dev1 = hw->dev[1]; | 3346 | dev1 = hw->dev[1]; |
3318 | if (dev1) | 3347 | if (dev1) |
3319 | unregister_netdev(dev1); | 3348 | unregister_netdev(dev1); |
3320 | unregister_netdev(dev0); | 3349 | unregister_netdev(dev0); |
3321 | 3350 | ||
3322 | sky2_write32(hw, B0_IMSK, 0); | ||
3323 | sky2_set_power_state(hw, PCI_D3hot); | 3351 | sky2_set_power_state(hw, PCI_D3hot); |
3324 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3352 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3325 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3353 | sky2_write8(hw, B0_CTST, CS_RST_SET); |