summaryrefslogtreecommitdiffstats
path: root/drivers/net/r6040.c
diff options
context:
space:
mode:
authorLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2009-01-14 16:29:08 +1100
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2009-01-14 16:29:08 +1100
commitc088f4e9da74b901f7ed1749ad697d77622ed0f9 (patch)
tree84cddf20369f82f10c1c3712e6cce20dd1b9d863 /drivers/net/r6040.c
parentce79735c12d62c3cda38eb31762cf98e87c7b087 (diff)
parenta6525042bfdfcab128bd91fad264de10fd24a55e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/net/r6040.c')
-rw-r--r--drivers/net/r6040.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 53bbddfc8c9..72fd9e97c19 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.19"
-#define DRV_RELDATE "18Dec2008"
+#define DRV_VERSION "0.21"
+#define DRV_RELDATE "09Jan2009"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -200,7 +200,7 @@ struct r6040_private {
static char version[] __devinitdata = KERN_INFO DRV_NAME
": RDC R6040 NAPI net driver,"
- "version "DRV_VERSION " (" DRV_RELDATE ")\n";
+ "version "DRV_VERSION " (" DRV_RELDATE ")";
static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
@@ -330,7 +330,7 @@ static int r6040_alloc_rxbufs(struct net_device *dev)
do {
skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
if (!skb) {
- printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+ printk(KERN_ERR DRV_NAME "%s: failed to alloc skb for rx\n", dev->name);
rc = -ENOMEM;
goto err_exit;
}
@@ -457,22 +457,12 @@ static void r6040_down(struct net_device *dev)
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
- free_irq(dev->irq, dev);
-
- /* Free RX buffer */
- r6040_free_rxbufs(dev);
-
- /* Free TX buffer */
- r6040_free_txbufs(dev);
-
- /* Free Descriptor memory */
- pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
- pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
}
static int r6040_close(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
+ struct pci_dev *pdev = lp->pdev;
/* deleted timer */
del_timer_sync(&lp->timer);
@@ -481,8 +471,28 @@ static int r6040_close(struct net_device *dev)
napi_disable(&lp->napi);
netif_stop_queue(dev);
r6040_down(dev);
+
+ free_irq(dev->irq, dev);
+
+ /* Free RX buffer */
+ r6040_free_rxbufs(dev);
+
+ /* Free TX buffer */
+ r6040_free_txbufs(dev);
+
spin_unlock_irq(&lp->lock);
+ /* Free Descriptor memory */
+ if (lp->rx_ring) {
+ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+ lp->rx_ring = 0;
+ }
+
+ if (lp->tx_ring) {
+ pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+ lp->tx_ring = 0;
+ }
+
return 0;
}
@@ -1049,6 +1059,7 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_set_multicast_list = r6040_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = r6040_ioctl,
.ndo_tx_timeout = r6040_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1077,20 +1088,20 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* this should always be supported */
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
"not supported by the card\n");
goto err_out;
}
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
"not supported by the card\n");
goto err_out;
}
/* IO Size check */
if (pci_resource_len(pdev, 0) < io_size) {
- printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n");
+ printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n");
err = -EIO;
goto err_out;
}
@@ -1100,7 +1111,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct r6040_private));
if (!dev) {
- printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n");
+ printk(KERN_ERR DRV_NAME ": Failed to allocate etherdev\n");
err = -ENOMEM;
goto err_out;
}
@@ -1116,11 +1127,15 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
ioaddr = pci_iomap(pdev, bar, io_size);
if (!ioaddr) {
- printk(KERN_ERR "ioremap failed for device %s\n",
+ printk(KERN_ERR DRV_NAME ": ioremap failed for device %s\n",
pci_name(pdev));
err = -EIO;
goto err_out_free_res;
}
+ /* If PHY status change register is still set to zero it means the
+ * bootloader didn't initialize it */
+ if (ioread16(ioaddr + PHY_CC) == 0)
+ iowrite16(0x9f07, ioaddr + PHY_CC);
/* Init system & device */
lp->base = ioaddr;
@@ -1137,6 +1152,13 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
adrp[1] = ioread16(ioaddr + MID_0M);
adrp[2] = ioread16(ioaddr + MID_0H);
+ /* Some bootloader/BIOSes do not initialize
+ * MAC address, warn about that */
+ if (!(adrp[0] || adrp[1] || adrp[2])) {
+ printk(KERN_WARNING DRV_NAME ": MAC address not initialized, generating random\n");
+ random_ether_addr(dev->dev_addr);
+ }
+
/* Link new device into r6040_root_dev */
lp->pdev = pdev;
lp->dev = dev;