diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 109 |
1 files changed, 21 insertions, 88 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ca8160d68229..73260364cba3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -74,7 +74,7 @@ | |||
74 | #define TX_RING_SIZE 512 | 74 | #define TX_RING_SIZE 512 |
75 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) | 75 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) |
76 | #define TX_MIN_PENDING 64 | 76 | #define TX_MIN_PENDING 64 |
77 | #define MAX_SKB_TX_LE (4 + 2*MAX_SKB_FRAGS) | 77 | #define MAX_SKB_TX_LE (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS) |
78 | 78 | ||
79 | #define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */ | 79 | #define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */ |
80 | #define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le)) | 80 | #define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le)) |
@@ -96,10 +96,6 @@ static int copybreak __read_mostly = 256; | |||
96 | module_param(copybreak, int, 0); | 96 | module_param(copybreak, int, 0); |
97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); | 97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); |
98 | 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 | |||
103 | static const struct pci_device_id sky2_id_table[] = { | 99 | static const struct pci_device_id sky2_id_table[] = { |
104 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
105 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
@@ -626,8 +622,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
626 | 622 | ||
627 | /* Configure Rx MAC FIFO */ | 623 | /* Configure Rx MAC FIFO */ |
628 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); | 624 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); |
629 | sky2_write16(hw, SK_REG(port, RX_GMF_CTRL_T), | 625 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), |
630 | GMF_RX_CTRL_DEF); | 626 | GMF_OPER_ON | GMF_RX_F_FL_ON); |
631 | 627 | ||
632 | /* Flush Rx MAC FIFO on any flow control or error */ | 628 | /* Flush Rx MAC FIFO on any flow control or error */ |
633 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); | 629 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); |
@@ -999,6 +995,10 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
999 | sky2_rx_add(sky2, re->mapaddr); | 995 | sky2_rx_add(sky2, re->mapaddr); |
1000 | } | 996 | } |
1001 | 997 | ||
998 | /* Truncate oversize frames */ | ||
999 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8); | ||
1000 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | ||
1001 | |||
1002 | /* Tell chip about available buffers */ | 1002 | /* Tell chip about available buffers */ |
1003 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1003 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); |
1004 | sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX)); | 1004 | sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX)); |
@@ -1149,6 +1149,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1149 | struct sky2_tx_le *le = NULL; | 1149 | struct sky2_tx_le *le = NULL; |
1150 | struct tx_ring_info *re; | 1150 | struct tx_ring_info *re; |
1151 | unsigned i, len; | 1151 | unsigned i, len; |
1152 | int avail; | ||
1152 | dma_addr_t mapping; | 1153 | dma_addr_t mapping; |
1153 | u32 addr64; | 1154 | u32 addr64; |
1154 | u16 mss; | 1155 | u16 mss; |
@@ -1291,12 +1292,16 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1291 | re->idx = sky2->tx_prod; | 1292 | re->idx = sky2->tx_prod; |
1292 | le->ctrl |= EOP; | 1293 | le->ctrl |= EOP; |
1293 | 1294 | ||
1295 | avail = tx_avail(sky2); | ||
1296 | if (mss != 0 || avail < TX_MIN_PENDING) { | ||
1297 | le->ctrl |= FRC_STAT; | ||
1298 | if (avail <= MAX_SKB_TX_LE) | ||
1299 | netif_stop_queue(dev); | ||
1300 | } | ||
1301 | |||
1294 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod, | 1302 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod, |
1295 | &sky2->tx_last_put, TX_RING_SIZE); | 1303 | &sky2->tx_last_put, TX_RING_SIZE); |
1296 | 1304 | ||
1297 | if (tx_avail(sky2) <= MAX_SKB_TX_LE) | ||
1298 | netif_stop_queue(dev); | ||
1299 | |||
1300 | out_unlock: | 1305 | out_unlock: |
1301 | spin_unlock(&sky2->tx_lock); | 1306 | spin_unlock(&sky2->tx_lock); |
1302 | 1307 | ||
@@ -1711,10 +1716,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1711 | 1716 | ||
1712 | 1717 | ||
1713 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | 1718 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) |
1714 | /* Want receive buffer size to be multiple of 64 bits, and incl room for vlan */ | 1719 | /* Want receive buffer size to be multiple of 64 bits |
1720 | * and incl room for vlan and truncation | ||
1721 | */ | ||
1715 | static inline unsigned sky2_buf_size(int mtu) | 1722 | static inline unsigned sky2_buf_size(int mtu) |
1716 | { | 1723 | { |
1717 | return roundup(mtu + ETH_HLEN + 4, 8); | 1724 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1718 | } | 1725 | } |
1719 | 1726 | ||
1720 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1727 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -1797,7 +1804,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2, | |||
1797 | if (!(status & GMR_FS_RX_OK)) | 1804 | if (!(status & GMR_FS_RX_OK)) |
1798 | goto resubmit; | 1805 | goto resubmit; |
1799 | 1806 | ||
1800 | if ((status >> 16) != length || length > sky2->rx_bufsize) | 1807 | if (length > sky2->netdev->mtu + ETH_HLEN) |
1801 | goto oversize; | 1808 | goto oversize; |
1802 | 1809 | ||
1803 | if (length < copybreak) { | 1810 | if (length < copybreak) { |
@@ -3126,61 +3133,6 @@ static void __devinit sky2_show_addr(struct net_device *dev) | |||
3126 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | 3133 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); |
3127 | } | 3134 | } |
3128 | 3135 | ||
3129 | /* Handle software interrupt used during MSI test */ | ||
3130 | static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, | ||
3131 | struct pt_regs *regs) | ||
3132 | { | ||
3133 | struct sky2_hw *hw = dev_id; | ||
3134 | u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
3135 | |||
3136 | if (status == 0) | ||
3137 | return IRQ_NONE; | ||
3138 | |||
3139 | if (status & Y2_IS_IRQ_SW) { | ||
3140 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3141 | hw->msi = 1; | ||
3142 | } | ||
3143 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
3144 | |||
3145 | sky2_read32(hw, B0_IMSK); | ||
3146 | return IRQ_HANDLED; | ||
3147 | } | ||
3148 | |||
3149 | /* Test interrupt path by forcing a a software IRQ */ | ||
3150 | static int __devinit sky2_test_msi(struct sky2_hw *hw) | ||
3151 | { | ||
3152 | struct pci_dev *pdev = hw->pdev; | ||
3153 | int i, err; | ||
3154 | |||
3155 | sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); | ||
3156 | |||
3157 | err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); | ||
3158 | if (err) { | ||
3159 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
3160 | pci_name(pdev), pdev->irq); | ||
3161 | return err; | ||
3162 | } | ||
3163 | |||
3164 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | ||
3165 | wmb(); | ||
3166 | |||
3167 | for (i = 0; i < 10; i++) { | ||
3168 | barrier(); | ||
3169 | if (hw->msi) | ||
3170 | goto found; | ||
3171 | mdelay(1); | ||
3172 | } | ||
3173 | |||
3174 | err = -EOPNOTSUPP; | ||
3175 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3176 | found: | ||
3177 | sky2_write32(hw, B0_IMSK, 0); | ||
3178 | |||
3179 | free_irq(pdev->irq, hw); | ||
3180 | |||
3181 | return err; | ||
3182 | } | ||
3183 | |||
3184 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3136 | static int __devinit sky2_probe(struct pci_dev *pdev, |
3185 | const struct pci_device_id *ent) | 3137 | const struct pci_device_id *ent) |
3186 | { | 3138 | { |
@@ -3302,22 +3254,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3302 | } | 3254 | } |
3303 | } | 3255 | } |
3304 | 3256 | ||
3305 | if (!disable_msi && pci_enable_msi(pdev) == 0) { | 3257 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); |
3306 | err = sky2_test_msi(hw); | ||
3307 | if (err == -EOPNOTSUPP) { | ||
3308 | /* MSI test failed, go back to INTx mode */ | ||
3309 | printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " | ||
3310 | "switching to INTx mode. Please report this failure to " | ||
3311 | "the PCI maintainer and include system chipset information.\n", | ||
3312 | pci_name(pdev)); | ||
3313 | pci_disable_msi(pdev); | ||
3314 | } | ||
3315 | else if (err) | ||
3316 | goto err_out_unregister; | ||
3317 | } | ||
3318 | |||
3319 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, | ||
3320 | DRV_NAME, hw); | ||
3321 | if (err) { | 3258 | if (err) { |
3322 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3259 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", |
3323 | pci_name(pdev), pdev->irq); | 3260 | pci_name(pdev), pdev->irq); |
@@ -3332,8 +3269,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3332 | return 0; | 3269 | return 0; |
3333 | 3270 | ||
3334 | err_out_unregister: | 3271 | err_out_unregister: |
3335 | if (hw->msi) | ||
3336 | pci_disable_msi(pdev); | ||
3337 | if (dev1) { | 3272 | if (dev1) { |
3338 | unregister_netdev(dev1); | 3273 | unregister_netdev(dev1); |
3339 | free_netdev(dev1); | 3274 | free_netdev(dev1); |
@@ -3376,8 +3311,6 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3376 | sky2_read8(hw, B0_CTST); | 3311 | sky2_read8(hw, B0_CTST); |
3377 | 3312 | ||
3378 | free_irq(pdev->irq, hw); | 3313 | free_irq(pdev->irq, hw); |
3379 | if (hw->msi) | ||
3380 | pci_disable_msi(pdev); | ||
3381 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 3314 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
3382 | pci_release_regions(pdev); | 3315 | pci_release_regions(pdev); |
3383 | pci_disable_device(pdev); | 3316 | pci_disable_device(pdev); |