Commit 543cec51 authored by Jens Osterkamp's avatar Jens Osterkamp Committed by Jeff Garzik

[PATCH] net: update the spider_net driver

- Prevent PCI posting problems by using synchronous register access
  in critical places

- Check return value from firmware device tree functions

- fix device cleanup
Signed-off-by: default avatarArnd Bergmann <arndb@de.ibm.com>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent aaec0fab
...@@ -108,6 +108,23 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value) ...@@ -108,6 +108,23 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
writel(value, card->regs + reg); writel(value, card->regs + reg);
} }
/**
* spider_net_write_reg_sync - writes to an SMMIO register of a card
* @card: device structure
* @reg: register to write to
* @value: value to write into the specified SMMIO register
*
* Unlike spider_net_write_reg, this will also make sure the
* data arrives on the card by reading the reg again.
*/
static void
spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
{
value = cpu_to_le32(value);
writel(value, card->regs + reg);
(void)readl(card->regs + reg);
}
/** /**
* spider_net_rx_irq_off - switch off rx irq on this spider card * spider_net_rx_irq_off - switch off rx irq on this spider card
* @card: device structure * @card: device structure
...@@ -123,7 +140,7 @@ spider_net_rx_irq_off(struct spider_net_card *card) ...@@ -123,7 +140,7 @@ spider_net_rx_irq_off(struct spider_net_card *card)
spin_lock_irqsave(&card->intmask_lock, flags); spin_lock_irqsave(&card->intmask_lock, flags);
regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
regvalue &= ~SPIDER_NET_RXINT; regvalue &= ~SPIDER_NET_RXINT;
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue); spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
spin_unlock_irqrestore(&card->intmask_lock, flags); spin_unlock_irqrestore(&card->intmask_lock, flags);
} }
...@@ -196,7 +213,7 @@ spider_net_rx_irq_on(struct spider_net_card *card) ...@@ -196,7 +213,7 @@ spider_net_rx_irq_on(struct spider_net_card *card)
spin_lock_irqsave(&card->intmask_lock, flags); spin_lock_irqsave(&card->intmask_lock, flags);
regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
regvalue |= SPIDER_NET_RXINT; regvalue |= SPIDER_NET_RXINT;
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue); spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
spin_unlock_irqrestore(&card->intmask_lock, flags); spin_unlock_irqrestore(&card->intmask_lock, flags);
} }
...@@ -215,7 +232,7 @@ spider_net_tx_irq_off(struct spider_net_card *card) ...@@ -215,7 +232,7 @@ spider_net_tx_irq_off(struct spider_net_card *card)
spin_lock_irqsave(&card->intmask_lock, flags); spin_lock_irqsave(&card->intmask_lock, flags);
regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
regvalue &= ~SPIDER_NET_TXINT; regvalue &= ~SPIDER_NET_TXINT;
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue); spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
spin_unlock_irqrestore(&card->intmask_lock, flags); spin_unlock_irqrestore(&card->intmask_lock, flags);
} }
...@@ -234,7 +251,7 @@ spider_net_tx_irq_on(struct spider_net_card *card) ...@@ -234,7 +251,7 @@ spider_net_tx_irq_on(struct spider_net_card *card)
spin_lock_irqsave(&card->intmask_lock, flags); spin_lock_irqsave(&card->intmask_lock, flags);
regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
regvalue |= SPIDER_NET_TXINT; regvalue |= SPIDER_NET_TXINT;
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue); spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
spin_unlock_irqrestore(&card->intmask_lock, flags); spin_unlock_irqrestore(&card->intmask_lock, flags);
} }
...@@ -813,6 +830,9 @@ spider_net_stop(struct net_device *netdev) ...@@ -813,6 +830,9 @@ spider_net_stop(struct net_device *netdev)
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
/* free_irq(netdev->irq, netdev);*/
free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_DMA_TX_FEND_VALUE); SPIDER_NET_DMA_TX_FEND_VALUE);
...@@ -822,10 +842,6 @@ spider_net_stop(struct net_device *netdev) ...@@ -822,10 +842,6 @@ spider_net_stop(struct net_device *netdev)
/* release chains */ /* release chains */
spider_net_release_tx_chain(card, 1); spider_net_release_tx_chain(card, 1);
/* switch off card */
spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
SPIDER_NET_CKRCTRL_STOP_VALUE);
spider_net_free_chain(card, &card->tx_chain); spider_net_free_chain(card, &card->tx_chain);
spider_net_free_chain(card, &card->rx_chain); spider_net_free_chain(card, &card->rx_chain);
...@@ -1745,6 +1761,10 @@ spider_net_open(struct net_device *netdev) ...@@ -1745,6 +1761,10 @@ spider_net_open(struct net_device *netdev)
spider_net_enable_card(card); spider_net_enable_card(card);
netif_start_queue(netdev);
netif_carrier_on(netdev);
netif_poll_enable(netdev);
return 0; return 0;
register_int_failed: register_int_failed:
...@@ -2045,7 +2065,12 @@ spider_net_setup_netdev(struct spider_net_card *card) ...@@ -2045,7 +2065,12 @@ spider_net_setup_netdev(struct spider_net_card *card)
netdev->irq = card->pdev->irq; netdev->irq = card->pdev->irq;
dn = pci_device_to_OF_node(card->pdev); dn = pci_device_to_OF_node(card->pdev);
if (!dn)
return -EIO;
mac = (u8 *)get_property(dn, "local-mac-address", NULL); mac = (u8 *)get_property(dn, "local-mac-address", NULL);
if (!mac)
return -EIO;
memcpy(addr.sa_data, mac, ETH_ALEN); memcpy(addr.sa_data, mac, ETH_ALEN);
result = spider_net_set_mac(netdev, &addr); result = spider_net_set_mac(netdev, &addr);
...@@ -2243,10 +2268,15 @@ spider_net_remove(struct pci_dev *pdev) ...@@ -2243,10 +2268,15 @@ spider_net_remove(struct pci_dev *pdev)
atomic_read(&card->tx_timeout_task_counter) == 0); atomic_read(&card->tx_timeout_task_counter) == 0);
unregister_netdev(netdev); unregister_netdev(netdev);
/* switch off card */
spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
SPIDER_NET_CKRCTRL_STOP_VALUE);
spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
SPIDER_NET_CKRCTRL_RUN_VALUE);
spider_net_undo_pci_setup(card); spider_net_undo_pci_setup(card);
free_netdev(netdev); free_netdev(netdev);
free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
} }
static struct pci_driver spider_net_driver = { static struct pci_driver spider_net_driver = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment