Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2004-02-15 02:41:32 -0800
committerLinus Torvalds <torvalds@home.osdl.org>2004-02-15 02:41:32 -0800
commite93aa38371fff48b5fd95492c0903ca6bf1224fd (patch)
tree4aeebe0f6d13fc41261cd00b785124c273a18885
parentc727c2f4ac83a67d3de8cdc345fc42f2d9b2f982 (diff)
[PATCH] Update mac network drivers
This should merge up the final piece of the ppc32/64 saga: the mac PowerMac MACE and Airport network drivers. Both of them are ported to the mac-io infrastructure, all probe code rewritting & cleaned up, better error handling & resource management.
-rw-r--r--drivers/net/mace.c239
-rw-r--r--drivers/net/wireless/airport.c51
2 files changed, 167 insertions, 123 deletions
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 2cf50b1ad277..3f5033046fbc 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -20,9 +20,10 @@
#include <asm/dbdma.h>
#include <asm/io.h>
#include <asm/pgtable.h>
+#include <asm/macio.h>
+
#include "mace.h"
-static struct net_device *mace_devs;
static int port_aaui = -1;
#define N_RX_RING 8
@@ -61,8 +62,7 @@ struct mace_data {
int timeout_active;
int port_aaui;
int chipid;
- struct device_node* of_node;
- struct net_device *next_mace;
+ struct macio_dev *mdev;
spinlock_t lock;
};
@@ -76,8 +76,6 @@ struct mace_data {
+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
static int bitrev(int);
-static int mace_probe(void);
-static void mace_probe1(struct device_node *mace);
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
@@ -110,26 +108,19 @@ bitrev(int b)
return d;
}
-static int __init mace_probe(void)
-{
- struct device_node *mace;
-
- for (mace = find_devices("mace"); mace != NULL; mace = mace->next)
- mace_probe1(mace);
- return mace_devs? 0: -ENODEV;
-}
-static void __init mace_probe1(struct device_node *mace)
+static int __devinit mace_probe(struct macio_dev *mdev, const struct of_match *match)
{
- int j, rev;
+ struct device_node *mace = macio_get_of_node(mdev);
struct net_device *dev;
struct mace_data *mp;
unsigned char *addr;
+ int j, rev, rc = -EBUSY;
- if (mace->n_addrs != 3 || mace->n_intrs != 3) {
+ if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
mace->full_name);
- return;
+ return -ENODEV;
}
addr = get_property(mace, "mac-address", NULL);
@@ -138,48 +129,48 @@ static void __init mace_probe1(struct device_node *mace)
if (addr == NULL) {
printk(KERN_ERR "Can't get mac-address for MACE %s\n",
mace->full_name);
- return;
+ return -ENODEV;
}
}
/*
- * lazy allocation - it's a driver-wide thing and it will live until
- * the unload, but we don't allocate it until it's needed
+ * lazy allocate the driver-wide dummy buffer. (Note that we
+ * never have more than one MACE in the system anyway)
*/
if (dummy_buf == NULL) {
dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
if (dummy_buf == NULL) {
printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n");
- return;
+ return -ENOMEM;
}
}
+ if (macio_request_resources(mdev, "mace")) {
+ printk(KERN_ERR "MACE: can't request IO resources !\n");
+ return -EBUSY;
+ }
+
dev = alloc_etherdev(PRIV_BYTES);
- if (!dev)
- return;
+ if (!dev) {
+ printk(KERN_ERR "MACE: can't allocate ethernet device !\n");
+ rc = -ENOMEM;
+ goto err_release;
+ }
SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
mp = dev->priv;
- mp->of_node = mace;
-
- if (!request_OF_resource(mace, 0, " (mace)")) {
- printk(KERN_ERR "MACE: can't request IO resource !\n");
- goto out1;
- }
- if (!request_OF_resource(mace, 1, " (mace tx dma)")) {
- printk(KERN_ERR "MACE: can't request TX DMA resource !\n");
- goto out2;
+ mp->mdev = mdev;
+ macio_set_drvdata(mdev, dev);
+
+ dev->base_addr = macio_resource_start(mdev, 0);
+ mp->mace = (volatile struct mace *)ioremap(dev->base_addr, 0x1000);
+ if (mp->mace == NULL) {
+ printk(KERN_ERR "MACE: can't map IO resources !\n");
+ rc = -ENOMEM;
+ goto err_free;
}
-
- if (!request_OF_resource(mace, 2, " (mace tx dma)")) {
- printk(KERN_ERR "MACE: can't request RX DMA resource !\n");
- goto out3;
- }
-
- dev->base_addr = mace->addrs[0].address;
- mp->mace = (volatile struct mace *)
- ioremap(mace->addrs[0].address, 0x1000);
- dev->irq = mace->intrs[0].line;
+ dev->irq = macio_irq(mdev, 0);
printk(KERN_INFO "%s: MACE at", dev->name);
rev = addr[0] == 0 && addr[1] == 0xA0;
@@ -194,12 +185,24 @@ static void __init mace_probe1(struct device_node *mace)
mp = (struct mace_data *) dev->priv;
mp->maccc = ENXMT | ENRCV;
+
mp->tx_dma = (volatile struct dbdma_regs *)
- ioremap(mace->addrs[1].address, 0x1000);
- mp->tx_dma_intr = mace->intrs[1].line;
+ ioremap(macio_resource_start(mdev, 1), 0x1000);
+ if (mp->tx_dma == NULL) {
+ printk(KERN_ERR "MACE: can't map TX DMA resources !\n");
+ rc = -ENOMEM;
+ goto err_unmap_io;
+ }
+ mp->tx_dma_intr = macio_irq(mdev, 1);
+
mp->rx_dma = (volatile struct dbdma_regs *)
- ioremap(mace->addrs[2].address, 0x1000);
- mp->rx_dma_intr = mace->intrs[2].line;
+ ioremap(macio_resource_start(mdev, 2), 0x1000);
+ if (mp->rx_dma == NULL) {
+ printk(KERN_ERR "MACE: can't map RX DMA resources !\n");
+ rc = -ENOMEM;
+ goto err_unmap_tx_dma;
+ }
+ mp->rx_dma_intr = macio_irq(mdev, 2);;
mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
@@ -233,43 +236,81 @@ static void __init mace_probe1(struct device_node *mace)
dev->set_multicast_list = mace_set_multicast;
dev->set_mac_address = mace_set_address;
+ /*
+ * Most of what is below could be moved to mace_open()
+ */
mace_reset(dev);
- if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+ rc = request_irq(dev->irq, mace_interrupt, 0, "MACE", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
- goto out4;
+ goto err_unmap_rx_dma;
}
- if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
- dev)) {
+ rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
- goto out5;
+ goto err_free_irq;
}
- if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
- dev)) {
+ rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
- goto out6;
+ goto err_free_tx_irq;
}
- if (register_netdev(dev) != 0)
- goto out7;
- mp->next_mace = mace_devs;
- mace_devs = dev;
- return;
-
-out7:
- free_irq(mp->rx_dma_intr, dev);
-out6:
- free_irq(mp->tx_dma_intr, dev);
-out5:
+ rc = register_netdev(dev);
+ if (rc) {
+ printk(KERN_ERR "Cannot register net device, aborting.\n");
+ goto err_free_rx_irq;
+ }
+
+ return 0;
+
+ err_free_rx_irq:
+ free_irq(macio_irq(mdev, 2), dev);
+ err_free_tx_irq:
+ free_irq(macio_irq(mdev, 1), dev);
+ err_free_irq:
+ free_irq(macio_irq(mdev, 0), dev);
+ err_unmap_rx_dma:
+ iounmap((void*)mp->rx_dma);
+ err_unmap_tx_dma:
+ iounmap((void*)mp->tx_dma);
+ err_unmap_io:
+ iounmap((void*)mp->mace);
+ err_free:
+ free_netdev(dev);
+ err_release:
+ macio_release_resources(mdev);
+
+ return rc;
+}
+
+static int __devexit mace_remove(struct macio_dev *mdev)
+{
+ struct net_device *dev = macio_get_drvdata(mdev);
+ struct mace_data *mp;
+
+ BUG_ON(dev == NULL);
+
+ macio_set_drvdata(mdev, NULL);
+
+ mp = dev->priv;
+
+ unregister_netdev(dev);
+
free_irq(dev->irq, dev);
-out4:
- release_OF_resource(mp->of_node, 2);
-out3:
- release_OF_resource(mp->of_node, 1);
-out2:
- release_OF_resource(mp->of_node, 0);
-out1:
+ free_irq(mp->tx_dma_intr, dev);
+ free_irq(mp->rx_dma_intr, dev);
+
+ iounmap((void*)mp->rx_dma);
+ iounmap((void*)mp->tx_dma);
+ iounmap((void*)mp->mace);
+
free_netdev(dev);
+
+ macio_release_resources(mdev);
+
+ return 0;
}
static void dbdma_reset(volatile struct dbdma_regs *dma)
@@ -967,37 +1008,45 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-MODULE_AUTHOR("Paul Mackerras");
-MODULE_DESCRIPTION("PowerMac MACE driver.");
-MODULE_PARM(port_aaui, "i");
-MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
-MODULE_LICENSE("GPL");
+static struct of_match mace_match[] =
+{
+ {
+ .name = "mace",
+ .type = OF_ANY_MATCH,
+ .compatible = OF_ANY_MATCH
+ },
+ {},
+};
-static void __exit mace_cleanup (void)
+static struct macio_driver mace_driver =
{
- struct net_device *dev;
- struct mace_data *mp;
+ .name = "mace",
+ .match_table = mace_match,
+ .probe = mace_probe,
+ .remove = mace_remove,
+};
- while ((dev = mace_devs) != 0) {
- mp = (struct mace_data *) mace_devs->priv;
- mace_devs = mp->next_mace;
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- free_irq(mp->tx_dma_intr, dev);
- free_irq(mp->rx_dma_intr, dev);
+static int __init mace_init(void)
+{
+ return macio_register_driver(&mace_driver);
+}
- release_OF_resource(mp->of_node, 0);
- release_OF_resource(mp->of_node, 1);
- release_OF_resource(mp->of_node, 2);
+static void __exit mace_cleanup(void)
+{
+ macio_unregister_driver(&mace_driver);
- free_netdev(dev);
- }
- if (dummy_buf != NULL) {
+ if (dummy_buf) {
kfree(dummy_buf);
dummy_buf = NULL;
- }
+ }
}
-module_init(mace_probe);
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac MACE driver.");
+MODULE_PARM(port_aaui, "i");
+MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
+MODULE_LICENSE("GPL");
+
+module_init(mace_init);
module_exit(mace_cleanup);
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 5d80f9f2ba86..b2ad9cd94cc3 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -40,7 +40,7 @@
#define AIRPORT_IO_LEN (0x1000) /* one page */
struct airport {
- struct device_node *node;
+ struct macio_dev *mdev;
void *vaddr;
int irq_requested;
int ndev_registered;
@@ -51,7 +51,6 @@ airport_suspend(struct macio_dev *mdev, u32 state)
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
- struct airport *card = priv->card;
unsigned long flags;
int err;
@@ -76,7 +75,7 @@ airport_suspend(struct macio_dev *mdev, u32 state)
orinoco_unlock(priv, &flags);
disable_irq(dev->irq);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
return 0;
}
@@ -86,14 +85,14 @@ airport_resume(struct macio_dev *mdev)
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
- struct airport *card = priv->card;
unsigned long flags;
int err;
printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- mdelay(200);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/5);
enable_irq(dev->irq);
@@ -142,15 +141,13 @@ airport_detach(struct macio_dev *mdev)
iounmap(card->vaddr);
card->vaddr = 0;
- dev->base_addr = 0;
+ macio_release_resource(mdev, 0);
- release_OF_resource(card->node, 0);
-
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
- dev_set_drvdata(&mdev->ofdev.dev, NULL);
+ macio_set_drvdata(mdev, NULL);
free_netdev(dev);
return 0;
@@ -173,11 +170,11 @@ static int airport_hard_reset(struct orinoco_private *priv)
* off. */
disable_irq(dev->irq);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
enable_irq(dev->irq);
@@ -194,10 +191,9 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
struct net_device *dev;
struct airport *card;
unsigned long phys_addr;
- struct device_node *of_node = mdev->ofdev.node;
hermes_t *hw;
- if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
+ if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
return -ENODEV;
}
@@ -212,27 +208,26 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
card = priv->card;
hw = &priv->hw;
- card->node = of_node;
+ card->mdev = mdev;
- if (! request_OF_resource(of_node, 0, " (airport)")) {
+ if (macio_request_resource(mdev, 0, "airport")) {
printk(KERN_ERR "airport: can't request IO resource !\n");
free_netdev(dev);
- return -ENODEV;
+ return -EBUSY;
}
- dev->name[0] = '\0'; /* register_netdev will give us an ethX name */
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
- dev_set_drvdata(&mdev->ofdev.dev, dev);
+ macio_set_drvdata(mdev, dev);
/* Setup interrupts & base address */
- dev->irq = of_node->intrs[0].line;
- phys_addr = of_node->addrs[0].address; /* Physical address */
+ dev->irq = macio_irq(mdev, 0);
+ phys_addr = macio_resource_start(mdev, 0); /* Physical address */
printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
dev->base_addr = phys_addr;
card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
- if (! card->vaddr) {
+ if (!card->vaddr) {
printk("airport: ioremap() failed\n");
goto failed;
}
@@ -241,8 +236,8 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
HERMES_MEM, HERMES_16BIT_REGSPACING);
/* Power up card */
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
/* Reset it before we get the interrupt */