]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Update mac network drivers
authorJeff Garzik <jgarzik@pobox.com>
Sun, 15 Feb 2004 10:41:32 +0000 (02:41 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Sun, 15 Feb 2004 10:41:32 +0000 (02:41 -0800)
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.

drivers/net/mace.c
drivers/net/wireless/airport.c

index 2cf50b1ad2773c98d1c62cfe5fc53229249afb3f..3f5033046fbcc79b901f4ba6f000cd2e5edeb8a3 100644 (file)
 #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);
index 5d80f9f2ba86de02c114033a35bfff54fe6d8b2d..b2ad9cd94cc31cefd0b934deae0e43d615b7ec34 100644 (file)
@@ -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 */