mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 13:22:57 +00:00
[PATCH] sis900 kernel oops fix
Backport of fix described below. From: Herbert Xu <herbert@gondor.apana.org.au> Fix bug #4223. OK, this happened because we got preempted before sis900_mii_probe finished setting the sis_priv->mii. Theoretically this can happen with SMP as well but I suppose the number of SMP machines with sis900 is fairly small. Anyway, the fix is to make sure that sis900_mii_probe is done before the device can be opened. This patch does it by moving the setup before register_netdevice. Since the netdev name is not available before register_netdev, I've changed the relevant printk's to use pci_name instead. Note that one of those printk's may be called after register_netdev as well. Signed-off-by: Chris Wright <chrisw@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
2d11c167b9
commit
4b272ed1e7
1 changed files with 14 additions and 16 deletions
|
@ -236,7 +236,7 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
|
|||
signature = (u16) read_eeprom(ioaddr, EEPROMSignature);
|
||||
if (signature == 0xffff || signature == 0x0000) {
|
||||
printk (KERN_INFO "%s: Error EERPOM read %x\n",
|
||||
net_dev->name, signature);
|
||||
pci_name(pci_dev), signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -268,7 +268,7 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
|
|||
if (!isa_bridge)
|
||||
isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
|
||||
if (!isa_bridge) {
|
||||
printk("%s: Can not find ISA bridge\n", net_dev->name);
|
||||
printk("%s: Can not find ISA bridge\n", pci_name(pci_dev));
|
||||
return 0;
|
||||
}
|
||||
pci_read_config_byte(isa_bridge, 0x48, ®);
|
||||
|
@ -456,10 +456,6 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
net_dev->tx_timeout = sis900_tx_timeout;
|
||||
net_dev->watchdog_timeo = TX_TIMEOUT;
|
||||
net_dev->ethtool_ops = &sis900_ethtool_ops;
|
||||
|
||||
ret = register_netdev(net_dev);
|
||||
if (ret)
|
||||
goto err_unmap_rx;
|
||||
|
||||
/* Get Mac address according to the chip revision */
|
||||
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
|
||||
|
@ -476,7 +472,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
|
||||
if (ret == 0) {
|
||||
ret = -ENODEV;
|
||||
goto err_out_unregister;
|
||||
goto err_unmap_rx;
|
||||
}
|
||||
|
||||
/* 630ET : set the mii access mode as software-mode */
|
||||
|
@ -486,7 +482,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
/* probe for mii transceiver */
|
||||
if (sis900_mii_probe(net_dev) == 0) {
|
||||
ret = -ENODEV;
|
||||
goto err_out_unregister;
|
||||
goto err_unmap_rx;
|
||||
}
|
||||
|
||||
/* save our host bridge revision */
|
||||
|
@ -496,6 +492,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
ret = register_netdev(net_dev);
|
||||
if (ret)
|
||||
goto err_unmap_rx;
|
||||
|
||||
/* print some information about our NIC */
|
||||
printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
|
||||
card_name, ioaddr, net_dev->irq);
|
||||
|
@ -505,8 +505,6 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
|
||||
return 0;
|
||||
|
||||
err_out_unregister:
|
||||
unregister_netdev(net_dev);
|
||||
err_unmap_rx:
|
||||
pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
|
||||
sis_priv->rx_ring_dma);
|
||||
|
@ -533,6 +531,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
|
|||
static int __init sis900_mii_probe(struct net_device * net_dev)
|
||||
{
|
||||
struct sis900_private * sis_priv = net_dev->priv;
|
||||
const char *dev_name = pci_name(sis_priv->pci_dev);
|
||||
u16 poll_bit = MII_STAT_LINK, status = 0;
|
||||
unsigned long timeout = jiffies + 5 * HZ;
|
||||
int phy_addr;
|
||||
|
@ -582,21 +581,20 @@ static int __init sis900_mii_probe(struct net_device * net_dev)
|
|||
mii_phy->phy_types =
|
||||
(mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
|
||||
printk(KERN_INFO "%s: %s transceiver found at address %d.\n",
|
||||
net_dev->name, mii_chip_table[i].name,
|
||||
dev_name, mii_chip_table[i].name,
|
||||
phy_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
if( !mii_chip_table[i].phy_id1 ) {
|
||||
printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n",
|
||||
net_dev->name, phy_addr);
|
||||
dev_name, phy_addr);
|
||||
mii_phy->phy_types = UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (sis_priv->mii == NULL) {
|
||||
printk(KERN_INFO "%s: No MII transceivers found!\n",
|
||||
net_dev->name);
|
||||
printk(KERN_INFO "%s: No MII transceivers found!\n", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -621,7 +619,7 @@ static int __init sis900_mii_probe(struct net_device * net_dev)
|
|||
poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
printk(KERN_WARNING "%s: reset phy and link down now\n",
|
||||
net_dev->name);
|
||||
dev_name);
|
||||
return -ETIME;
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +689,7 @@ static u16 sis900_default_phy(struct net_device * net_dev)
|
|||
sis_priv->mii = default_phy;
|
||||
sis_priv->cur_phy = default_phy->phy_addr;
|
||||
printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
|
||||
net_dev->name,sis_priv->cur_phy);
|
||||
pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
|
||||
}
|
||||
|
||||
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
|
||||
|
|
Loading…
Reference in a new issue