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.c186
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;
102module_param(copybreak, int, 0); 96module_param(copybreak, int, 0);
103MODULE_PARM_DESC(copybreak, "Receive copy threshold"); 97MODULE_PARM_DESC(copybreak, "Receive copy threshold");
104 98
99static int disable_msi = 0;
100module_param(disable_msi, int, 0);
101MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
102
105static const struct pci_device_id sky2_id_table[] = { 103static 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
1915exit_loop: 1915exit_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
2142static int sky2_reset(struct sky2_hw *hw) 2140static 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
2296pci_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
2302static u32 sky2_supported_modes(const struct sky2_hw *hw) 2305static 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)
2551static int sky2_set_mac_address(struct net_device *dev, void *p) 2554static 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 */
3067static 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 */
3087static 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
3058static int __devinit sky2_probe(struct pci_dev *pdev, 3121static 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
3186err_out_unregister: 3270err_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)
3263static int sky2_resume(struct pci_dev *pdev) 3351static 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; 3379out:
3380 return err;
3285} 3381}
3286#endif 3382#endif
3287 3383