diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 186 |
1 files changed, 141 insertions, 45 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f8b973a04b65..cae2edf23004 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -23,12 +23,6 @@ | |||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* | ||
27 | * TOTEST | ||
28 | * - speed setting | ||
29 | * - suspend/resume | ||
30 | */ | ||
31 | |||
32 | #include <linux/config.h> | 26 | #include <linux/config.h> |
33 | #include <linux/crc32.h> | 27 | #include <linux/crc32.h> |
34 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
@@ -57,7 +51,7 @@ | |||
57 | #include "sky2.h" | 51 | #include "sky2.h" |
58 | 52 | ||
59 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
60 | #define DRV_VERSION "0.13" | 54 | #define DRV_VERSION "0.15" |
61 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
62 | 56 | ||
63 | /* | 57 | /* |
@@ -102,6 +96,10 @@ static int copybreak __read_mostly = 256; | |||
102 | module_param(copybreak, int, 0); | 96 | module_param(copybreak, int, 0); |
103 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); | 97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); |
104 | 98 | ||
99 | static int disable_msi = 0; | ||
100 | module_param(disable_msi, int, 0); | ||
101 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
102 | |||
105 | static const struct pci_device_id sky2_id_table[] = { | 103 | static const struct pci_device_id sky2_id_table[] = { |
106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 104 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 105 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
@@ -198,7 +196,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
198 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 196 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
199 | 197 | ||
200 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); | 198 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); |
201 | vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) && | 199 | vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && |
202 | (power_control & PCI_PM_CAP_PME_D3cold); | 200 | (power_control & PCI_PM_CAP_PME_D3cold); |
203 | 201 | ||
204 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); | 202 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); |
@@ -1834,6 +1832,8 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1834 | u16 hwidx; | 1832 | u16 hwidx; |
1835 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; | 1833 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; |
1836 | 1834 | ||
1835 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1836 | |||
1837 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | 1837 | hwidx = sky2_read16(hw, STAT_PUT_IDX); |
1838 | BUG_ON(hwidx >= STATUS_RING_SIZE); | 1838 | BUG_ON(hwidx >= STATUS_RING_SIZE); |
1839 | rmb(); | 1839 | rmb(); |
@@ -1913,12 +1913,10 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1913 | } | 1913 | } |
1914 | 1914 | ||
1915 | exit_loop: | 1915 | exit_loop: |
1916 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1917 | |||
1918 | sky2_tx_check(hw, 0, tx_done[0]); | 1916 | sky2_tx_check(hw, 0, tx_done[0]); |
1919 | sky2_tx_check(hw, 1, tx_done[1]); | 1917 | sky2_tx_check(hw, 1, tx_done[1]); |
1920 | 1918 | ||
1921 | if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) { | 1919 | if (likely(work_done < to_do)) { |
1922 | /* need to restart TX timer */ | 1920 | /* need to restart TX timer */ |
1923 | if (is_ec_a1(hw)) { | 1921 | if (is_ec_a1(hw)) { |
1924 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | 1922 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); |
@@ -2141,14 +2139,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2141 | 2139 | ||
2142 | static int sky2_reset(struct sky2_hw *hw) | 2140 | static int sky2_reset(struct sky2_hw *hw) |
2143 | { | 2141 | { |
2144 | u32 ctst; | ||
2145 | u16 status; | 2142 | u16 status; |
2146 | u8 t8, pmd_type; | 2143 | u8 t8, pmd_type; |
2147 | int i; | 2144 | int i, err; |
2148 | |||
2149 | ctst = sky2_read32(hw, B0_CTST); | ||
2150 | 2145 | ||
2151 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2146 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2147 | |||
2152 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); | 2148 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); |
2153 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { | 2149 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { |
2154 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", | 2150 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", |
@@ -2156,12 +2152,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2156 | return -EOPNOTSUPP; | 2152 | return -EOPNOTSUPP; |
2157 | } | 2153 | } |
2158 | 2154 | ||
2159 | /* ring for status responses */ | ||
2160 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | ||
2161 | &hw->st_dma); | ||
2162 | if (!hw->st_le) | ||
2163 | return -ENOMEM; | ||
2164 | |||
2165 | /* disable ASF */ | 2155 | /* disable ASF */ |
2166 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2156 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2167 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2157 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -2173,19 +2163,24 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2173 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2163 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2174 | 2164 | ||
2175 | /* clear PCI errors, if any */ | 2165 | /* clear PCI errors, if any */ |
2176 | pci_read_config_word(hw->pdev, PCI_STATUS, &status); | 2166 | err = pci_read_config_word(hw->pdev, PCI_STATUS, &status); |
2167 | if (err) | ||
2168 | goto pci_err; | ||
2169 | |||
2177 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2170 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
2178 | pci_write_config_word(hw->pdev, PCI_STATUS, | 2171 | err = pci_write_config_word(hw->pdev, PCI_STATUS, |
2179 | status | PCI_STATUS_ERROR_BITS); | 2172 | status | PCI_STATUS_ERROR_BITS); |
2173 | if (err) | ||
2174 | goto pci_err; | ||
2180 | 2175 | ||
2181 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); | 2176 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); |
2182 | 2177 | ||
2183 | /* clear any PEX errors */ | 2178 | /* clear any PEX errors */ |
2184 | if (is_pciex(hw)) { | 2179 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) { |
2185 | u16 lstat; | 2180 | err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, |
2186 | pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | 2181 | 0xffffffffUL); |
2187 | 0xffffffffUL); | 2182 | if (err) |
2188 | pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat); | 2183 | goto pci_err; |
2189 | } | 2184 | } |
2190 | 2185 | ||
2191 | pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2186 | pmd_type = sky2_read8(hw, B2_PMD_TYP); |
@@ -2297,6 +2292,14 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2297 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2292 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2298 | 2293 | ||
2299 | return 0; | 2294 | return 0; |
2295 | |||
2296 | pci_err: | ||
2297 | /* This is to catch a BIOS bug workaround where | ||
2298 | * mmconfig table doesn't have other buses. | ||
2299 | */ | ||
2300 | printk(KERN_ERR PFX "%s: can't access PCI config space\n", | ||
2301 | pci_name(hw->pdev)); | ||
2302 | return err; | ||
2300 | } | 2303 | } |
2301 | 2304 | ||
2302 | static u32 sky2_supported_modes(const struct sky2_hw *hw) | 2305 | static u32 sky2_supported_modes(const struct sky2_hw *hw) |
@@ -2551,19 +2554,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) | |||
2551 | static int sky2_set_mac_address(struct net_device *dev, void *p) | 2554 | static int sky2_set_mac_address(struct net_device *dev, void *p) |
2552 | { | 2555 | { |
2553 | struct sky2_port *sky2 = netdev_priv(dev); | 2556 | struct sky2_port *sky2 = netdev_priv(dev); |
2554 | struct sockaddr *addr = p; | 2557 | struct sky2_hw *hw = sky2->hw; |
2558 | unsigned port = sky2->port; | ||
2559 | const struct sockaddr *addr = p; | ||
2555 | 2560 | ||
2556 | if (!is_valid_ether_addr(addr->sa_data)) | 2561 | if (!is_valid_ether_addr(addr->sa_data)) |
2557 | return -EADDRNOTAVAIL; | 2562 | return -EADDRNOTAVAIL; |
2558 | 2563 | ||
2559 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 2564 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
2560 | memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8, | 2565 | memcpy_toio(hw->regs + B2_MAC_1 + port * 8, |
2561 | dev->dev_addr, ETH_ALEN); | 2566 | dev->dev_addr, ETH_ALEN); |
2562 | memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8, | 2567 | memcpy_toio(hw->regs + B2_MAC_2 + port * 8, |
2563 | dev->dev_addr, ETH_ALEN); | 2568 | dev->dev_addr, ETH_ALEN); |
2564 | 2569 | ||
2565 | if (netif_running(dev)) | 2570 | /* virtual address for data */ |
2566 | sky2_phy_reinit(sky2); | 2571 | gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); |
2572 | |||
2573 | /* physical address: used for pause frames */ | ||
2574 | gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); | ||
2567 | 2575 | ||
2568 | return 0; | 2576 | return 0; |
2569 | } | 2577 | } |
@@ -2843,7 +2851,7 @@ static int sky2_set_coalesce(struct net_device *dev, | |||
2843 | if (ecmd->rx_coalesce_usecs_irq == 0) | 2851 | if (ecmd->rx_coalesce_usecs_irq == 0) |
2844 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); | 2852 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); |
2845 | else { | 2853 | else { |
2846 | sky2_write32(hw, STAT_TX_TIMER_INI, | 2854 | sky2_write32(hw, STAT_ISR_TIMER_INI, |
2847 | sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); | 2855 | sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); |
2848 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2856 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2849 | } | 2857 | } |
@@ -3055,6 +3063,61 @@ static void __devinit sky2_show_addr(struct net_device *dev) | |||
3055 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | 3063 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); |
3056 | } | 3064 | } |
3057 | 3065 | ||
3066 | /* Handle software interrupt used during MSI test */ | ||
3067 | static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, | ||
3068 | struct pt_regs *regs) | ||
3069 | { | ||
3070 | struct sky2_hw *hw = dev_id; | ||
3071 | u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
3072 | |||
3073 | if (status == 0) | ||
3074 | return IRQ_NONE; | ||
3075 | |||
3076 | if (status & Y2_IS_IRQ_SW) { | ||
3077 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3078 | hw->msi = 1; | ||
3079 | } | ||
3080 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
3081 | |||
3082 | sky2_read32(hw, B0_IMSK); | ||
3083 | return IRQ_HANDLED; | ||
3084 | } | ||
3085 | |||
3086 | /* Test interrupt path by forcing a a software IRQ */ | ||
3087 | static int __devinit sky2_test_msi(struct sky2_hw *hw) | ||
3088 | { | ||
3089 | struct pci_dev *pdev = hw->pdev; | ||
3090 | int i, err; | ||
3091 | |||
3092 | sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); | ||
3093 | |||
3094 | err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); | ||
3095 | if (err) { | ||
3096 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
3097 | pci_name(pdev), pdev->irq); | ||
3098 | return err; | ||
3099 | } | ||
3100 | |||
3101 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | ||
3102 | wmb(); | ||
3103 | |||
3104 | for (i = 0; i < 10; i++) { | ||
3105 | barrier(); | ||
3106 | if (hw->msi) | ||
3107 | goto found; | ||
3108 | mdelay(1); | ||
3109 | } | ||
3110 | |||
3111 | err = -EOPNOTSUPP; | ||
3112 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3113 | found: | ||
3114 | sky2_write32(hw, B0_IMSK, 0); | ||
3115 | |||
3116 | free_irq(pdev->irq, hw); | ||
3117 | |||
3118 | return err; | ||
3119 | } | ||
3120 | |||
3058 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3121 | static int __devinit sky2_probe(struct pci_dev *pdev, |
3059 | const struct pci_device_id *ent) | 3122 | const struct pci_device_id *ent) |
3060 | { | 3123 | { |
@@ -3135,6 +3198,12 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3135 | } | 3198 | } |
3136 | hw->pm_cap = pm_cap; | 3199 | hw->pm_cap = pm_cap; |
3137 | 3200 | ||
3201 | /* ring for status responses */ | ||
3202 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | ||
3203 | &hw->st_dma); | ||
3204 | if (!hw->st_le) | ||
3205 | goto err_out_iounmap; | ||
3206 | |||
3138 | err = sky2_reset(hw); | 3207 | err = sky2_reset(hw); |
3139 | if (err) | 3208 | if (err) |
3140 | goto err_out_iounmap; | 3209 | goto err_out_iounmap; |
@@ -3169,7 +3238,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3169 | } | 3238 | } |
3170 | } | 3239 | } |
3171 | 3240 | ||
3172 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); | 3241 | if (!disable_msi && pci_enable_msi(pdev) == 0) { |
3242 | err = sky2_test_msi(hw); | ||
3243 | if (err == -EOPNOTSUPP) { | ||
3244 | /* MSI test failed, go back to INTx mode */ | ||
3245 | printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " | ||
3246 | "switching to INTx mode. Please report this failure to " | ||
3247 | "the PCI maintainer and include system chipset information.\n", | ||
3248 | pci_name(pdev)); | ||
3249 | pci_disable_msi(pdev); | ||
3250 | } | ||
3251 | else if (err) | ||
3252 | goto err_out_unregister; | ||
3253 | } | ||
3254 | |||
3255 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, | ||
3256 | DRV_NAME, hw); | ||
3173 | if (err) { | 3257 | if (err) { |
3174 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3258 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", |
3175 | pci_name(pdev), pdev->irq); | 3259 | pci_name(pdev), pdev->irq); |
@@ -3184,6 +3268,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3184 | return 0; | 3268 | return 0; |
3185 | 3269 | ||
3186 | err_out_unregister: | 3270 | err_out_unregister: |
3271 | if (hw->msi) | ||
3272 | pci_disable_msi(pdev); | ||
3187 | if (dev1) { | 3273 | if (dev1) { |
3188 | unregister_netdev(dev1); | 3274 | unregister_netdev(dev1); |
3189 | free_netdev(dev1); | 3275 | free_netdev(dev1); |
@@ -3226,6 +3312,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3226 | sky2_read8(hw, B0_CTST); | 3312 | sky2_read8(hw, B0_CTST); |
3227 | 3313 | ||
3228 | free_irq(pdev->irq, hw); | 3314 | free_irq(pdev->irq, hw); |
3315 | if (hw->msi) | ||
3316 | pci_disable_msi(pdev); | ||
3229 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 3317 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
3230 | pci_release_regions(pdev); | 3318 | pci_release_regions(pdev); |
3231 | pci_disable_device(pdev); | 3319 | pci_disable_device(pdev); |
@@ -3263,25 +3351,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3263 | static int sky2_resume(struct pci_dev *pdev) | 3351 | static int sky2_resume(struct pci_dev *pdev) |
3264 | { | 3352 | { |
3265 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3353 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3266 | int i; | 3354 | int i, err; |
3267 | 3355 | ||
3268 | pci_restore_state(pdev); | 3356 | pci_restore_state(pdev); |
3269 | pci_enable_wake(pdev, PCI_D0, 0); | 3357 | pci_enable_wake(pdev, PCI_D0, 0); |
3270 | sky2_set_power_state(hw, PCI_D0); | 3358 | err = sky2_set_power_state(hw, PCI_D0); |
3359 | if (err) | ||
3360 | goto out; | ||
3271 | 3361 | ||
3272 | sky2_reset(hw); | 3362 | err = sky2_reset(hw); |
3363 | if (err) | ||
3364 | goto out; | ||
3273 | 3365 | ||
3274 | for (i = 0; i < 2; i++) { | 3366 | for (i = 0; i < 2; i++) { |
3275 | struct net_device *dev = hw->dev[i]; | 3367 | struct net_device *dev = hw->dev[i]; |
3276 | if (dev) { | 3368 | if (dev && netif_running(dev)) { |
3277 | if (netif_running(dev)) { | 3369 | netif_device_attach(dev); |
3278 | netif_device_attach(dev); | 3370 | err = sky2_up(dev); |
3279 | if (sky2_up(dev)) | 3371 | if (err) { |
3280 | dev_close(dev); | 3372 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
3373 | dev->name, err); | ||
3374 | dev_close(dev); | ||
3375 | break; | ||
3281 | } | 3376 | } |
3282 | } | 3377 | } |
3283 | } | 3378 | } |
3284 | return 0; | 3379 | out: |
3380 | return err; | ||
3285 | } | 3381 | } |
3286 | #endif | 3382 | #endif |
3287 | 3383 | ||