From e93aa38371fff48b5fd95492c0903ca6bf1224fd Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 15 Feb 2004 02:41:32 -0800 Subject: [PATCH] [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. --- drivers/net/mace.c | 239 ++++++++++++++++++++------------- drivers/net/wireless/airport.c | 51 ++++--- 2 files changed, 167 insertions(+), 123 deletions(-) diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 2cf50b1ad2773..3f5033046fbcc 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -20,9 +20,10 @@ #include #include #include +#include + #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 5d80f9f2ba86d..b2ad9cd94cc31 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 */ -- 2.53.0