diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-04-27 04:55:26 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-27 04:55:26 -0400 |
| commit | 9a375e93f88269bb770fb2eaa57554c975449c88 (patch) | |
| tree | 4c8f6d77f0aa94fc69c5b9e75d51db1451bdf66f /drivers/net/sky2.c | |
| parent | b2b4b9a7c09ad66e095b13c97946a96f2dc8284e (diff) | |
| parent | acc696d93dcf993dec123d69d599979e1456ffec (diff) | |
Merge branch 'upstream' into max-sect
Diffstat (limited to 'drivers/net/sky2.c')
| -rw-r--r-- | drivers/net/sky2.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67b0eab16589..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 | /* |
| @@ -925,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
| 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
| 926 | if (likely(skb)) { | 926 | if (likely(skb)) { |
| 927 | unsigned long p = (unsigned long) skb->data; | 927 | unsigned long p = (unsigned long) skb->data; |
| 928 | skb_reserve(skb, | 928 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
| 929 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
| 930 | } | 929 | } |
| 931 | 930 | ||
| 932 | return skb; | 931 | return skb; |
| @@ -1686,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
| 1686 | } | 1685 | } |
| 1687 | 1686 | ||
| 1688 | 1687 | ||
| 1689 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
| 1690 | /* Want receive buffer size to be multiple of 64 bits | 1688 | /* Want receive buffer size to be multiple of 64 bits |
| 1691 | * and incl room for vlan and truncation | 1689 | * and incl room for vlan and truncation |
| 1692 | */ | 1690 | */ |
| 1693 | static inline unsigned sky2_buf_size(int mtu) | 1691 | static inline unsigned sky2_buf_size(int mtu) |
| 1694 | { | 1692 | { |
| 1695 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1693 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
| 1696 | } | 1694 | } |
| 1697 | 1695 | ||
| 1698 | 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) |
| @@ -2086,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
| 2086 | } | 2084 | } |
| 2087 | } | 2085 | } |
| 2088 | 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 | |||
| 2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2101 | static int sky2_poll(struct net_device *dev0, int *budget) |
| 2090 | { | 2102 | { |
| 2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2103 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
| @@ -2093,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2093 | int work_done = 0; | 2105 | int work_done = 0; |
| 2094 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
| 2095 | 2107 | ||
| 2108 | restart_poll: | ||
| 2096 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
| 2097 | if (status & Y2_IS_HW_ERR) | 2110 | if (status & Y2_IS_HW_ERR) |
| 2098 | sky2_hw_intr(hw); | 2111 | sky2_hw_intr(hw); |
| @@ -2123,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2123 | } | 2136 | } |
| 2124 | 2137 | ||
| 2125 | if (status & Y2_IS_STAT_BMU) { | 2138 | if (status & Y2_IS_STAT_BMU) { |
| 2126 | work_done = sky2_status_intr(hw, work_limit); | 2139 | work_done += sky2_status_intr(hw, work_limit - work_done); |
| 2127 | *budget -= work_done; | 2140 | *budget -= work_done; |
| 2128 | dev0->quota -= work_done; | 2141 | dev0->quota -= work_done; |
| 2129 | 2142 | ||
| @@ -2133,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2133 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
| 2134 | } | 2147 | } |
| 2135 | 2148 | ||
| 2136 | netif_rx_complete(dev0); | 2149 | mod_timer(&hw->idle_timer, jiffies + HZ); |
| 2150 | |||
| 2151 | local_irq_disable(); | ||
| 2152 | __netif_rx_complete(dev0); | ||
| 2137 | 2153 | ||
| 2138 | 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(); | ||
| 2139 | return 0; | 2167 | return 0; |
| 2140 | } | 2168 | } |
| 2141 | 2169 | ||
| @@ -2153,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
| 2153 | prefetch(&hw->st_le[hw->st_idx]); | 2181 | prefetch(&hw->st_le[hw->st_idx]); |
| 2154 | if (likely(__netif_rx_schedule_prep(dev0))) | 2182 | if (likely(__netif_rx_schedule_prep(dev0))) |
| 2155 | __netif_rx_schedule(dev0); | 2183 | __netif_rx_schedule(dev0); |
| 2156 | else | ||
| 2157 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
| 2158 | 2184 | ||
| 2159 | return IRQ_HANDLED; | 2185 | return IRQ_HANDLED; |
| 2160 | } | 2186 | } |
| @@ -2193,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
| 2193 | } | 2219 | } |
| 2194 | 2220 | ||
| 2195 | 2221 | ||
| 2196 | static int sky2_reset(struct sky2_hw *hw) | 2222 | static int __devinit sky2_reset(struct sky2_hw *hw) |
| 2197 | { | 2223 | { |
| 2198 | u16 status; | 2224 | u16 status; |
| 2199 | u8 t8, pmd_type; | 2225 | u8 t8, pmd_type; |
| @@ -3276,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3276 | 3302 | ||
| 3277 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
| 3278 | 3304 | ||
| 3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
| 3306 | |||
| 3279 | pci_set_drvdata(pdev, hw); | 3307 | pci_set_drvdata(pdev, hw); |
| 3280 | 3308 | ||
| 3281 | return 0; | 3309 | return 0; |
| @@ -3311,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 3311 | if (!hw) | 3339 | if (!hw) |
| 3312 | return; | 3340 | return; |
| 3313 | 3341 | ||
| 3342 | del_timer_sync(&hw->idle_timer); | ||
| 3343 | |||
| 3344 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3314 | dev0 = hw->dev[0]; | 3345 | dev0 = hw->dev[0]; |
| 3315 | dev1 = hw->dev[1]; | 3346 | dev1 = hw->dev[1]; |
| 3316 | if (dev1) | 3347 | if (dev1) |
| 3317 | unregister_netdev(dev1); | 3348 | unregister_netdev(dev1); |
| 3318 | unregister_netdev(dev0); | 3349 | unregister_netdev(dev0); |
| 3319 | 3350 | ||
| 3320 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3321 | sky2_set_power_state(hw, PCI_D3hot); | 3351 | sky2_set_power_state(hw, PCI_D3hot); |
| 3322 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3352 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
| 3323 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3353 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
