diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-05-18 11:16:21 -0700 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-05-20 00:15:39 -0400 |
commit | ee7abb04df92b444069be8fe47d66d809de23782 (patch) | |
tree | b96478a17f08aed0955ea6fba06cc9dde8f517fe /drivers/net/sky2.c | |
parent | 38bb6b288bf4fb954a3793e57c7339774c842a54 (diff) | |
download | linux-3.10-ee7abb04df92b444069be8fe47d66d809de23782.tar.gz linux-3.10-ee7abb04df92b444069be8fe47d66d809de23782.tar.bz2 linux-3.10-ee7abb04df92b444069be8fe47d66d809de23782.zip |
[PATCH] sky2: allow dual port usage
If both ports are receiving on the SysKonnect dual port cards,
then it appears the bus interface unit can give an interrupt status
for frame before DMA has completed. This leads to bogus frames
and general confusion. This is why receive checksumming is also
messed up on dual port cards.
A workaround for the out of order receive problem is to eliminating
split transactions on PCI-X.
This version is based of the current linux-2.6.git including earlier
patch to disable dual ports.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 62be6d99d05..277c57b3df9 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1020,19 +1020,26 @@ static int sky2_up(struct net_device *dev) struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; u32 ramsize, rxspace, imask; - int err; + int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; - /* Block bringing up both ports at the same time on a dual port card. - * There is an unfixed bug where receiver gets confused and picks up - * packets out of order. Until this is fixed, prevent data corruption. + /* + * On dual port PCI-X card, there is an problem where status + * can be received out of order due to split transactions */ - if (otherdev && netif_running(otherdev)) { - printk(KERN_INFO PFX "dual port support is disabled.\n"); - return -EBUSY; - } + if (otherdev && netif_running(otherdev) && + (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { + struct sky2_port *osky2 = netdev_priv(otherdev); + u16 cmd; + + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); + cmd &= ~PCI_X_CMD_MAX_SPLIT; + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); + + sky2->rx_csum = 0; + osky2->rx_csum = 0; + } - err = -ENOMEM; if (netif_msg_ifup(sky2)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); @@ -3078,12 +3085,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - - /* Receive checksum disabled for Yukon XL - * because of observed problems with incorrect - * values when multiple packets are received in one interrupt - */ - sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); + sky2->rx_csum = 1; spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; |