aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c58
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)");
99static const struct pci_device_id sky2_id_table[] = { 99static 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 */
1695static inline unsigned sky2_buf_size(int mtu) 1691static 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
1700static int sky2_change_mtu(struct net_device *dev, int new_mtu) 1696static 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 */
2090static 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
2091static int sky2_poll(struct net_device *dev0, int *budget) 2101static 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
2198static int sky2_reset(struct sky2_hw *hw) 2222static 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);