From c32262de8573da3184d4a32353d5a6eeccd13548 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 4 Feb 2004 18:48:16 -0500 Subject: [PATCH] [PATCH] bmac network driver update Hi ! I didn't include that with the bitkeeper based PowerMac updates so Jeff can assume his role as maintainer/filter of network driver updates :) Here's my latest update to this pmac-only driver, please apply if you are ok with it. The driver now uses the macio infrastructure for detection & power management notifications, getting into sysfs at the same time. Ben. # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/01/23 09:38:35+11:00 benh@kernel.crashing.org # Update PowerMac "bmac" driver to the "macio" device so it fits in sysfs # and gets proper power management ordering # # drivers/net/bmac.c # 2004/01/23 09:38:22+11:00 benh@kernel.crashing.org +185 -203 # Update PowerMac "bmac" driver to the "macio" device so it fits in sysfs # and gets proper power management ordering # --- drivers/net/bmac.c | 388 +++++++++++++++++++++------------------------ 1 file changed, 185 insertions(+), 203 deletions(-) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 27bc8ed937cfa..41c6792af8fc2 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -26,11 +26,9 @@ #include #include #include +#include #include -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#endif + #include "bmac.h" #define trunc_page(x) ((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1)))) @@ -67,7 +65,7 @@ struct bmac_data { int rx_dma_intr; volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */ volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */ - struct device_node *node; + struct macio_dev *mdev; int is_bmac_plus; struct sk_buff *rx_bufs[N_RX_RING]; int rx_fill; @@ -84,9 +82,10 @@ struct bmac_data { unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; spinlock_t lock; - struct net_device *next_bmac; }; +#if 0 /* Move that to ethtool */ + typedef struct bmac_reg_entry { char *name; unsigned short reg_offset; @@ -128,16 +127,10 @@ static bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = { {"RXCV", RXCV} }; -static struct net_device *bmac_devs; -static unsigned char *bmac_emergency_rxbuf; - -#ifdef CONFIG_PMAC_PBOOK -static int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when); -static struct pmu_sleep_notifier bmac_sleep_notifier = { - bmac_sleep_notify, SLEEP_LEVEL_NET, -}; #endif +static unsigned char *bmac_emergency_rxbuf; + /* * Number of bytes of private data per BMAC: allow enough for * the rx and tx dma commands plus a branch dma command each, @@ -149,7 +142,6 @@ static struct pmu_sleep_notifier bmac_sleep_notifier = { + sizeof(struct sk_buff_head)) static unsigned char bitrev(unsigned char b); -static void bmac_probe1(struct device_node *bmac, int is_bmac_plus); static int bmac_open(struct net_device *dev); static int bmac_close(struct net_device *dev); static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev); @@ -166,7 +158,6 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void bmac_set_timeout(struct net_device *dev); static void bmac_tx_timeout(unsigned long data); -static int bmac_proc_info ( char *buffer, char **start, off_t offset, int length); static int bmac_output(struct sk_buff *skb, struct net_device *dev); static void bmac_start(struct net_device *dev); @@ -244,7 +235,7 @@ bmac_enable_and_reset_chip(struct net_device *dev) if (td) dbdma_reset(td); - pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 1); + pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 1); } #define MIFDELAY udelay(10) @@ -457,87 +448,80 @@ bmac_init_phy(struct net_device *dev) } } -static void -bmac_init_chip(struct net_device *dev) +static void bmac_init_chip(struct net_device *dev) { bmac_init_phy(dev); bmac_init_registers(dev); } -#ifdef CONFIG_PMAC_PBOOK -static int -bmac_sleep_notify(struct pmu_sleep_notifier *self, int when) +#ifdef CONFIG_PM +static int bmac_suspend(struct macio_dev *mdev, u32 state) { - struct bmac_data *bp; + struct net_device* dev = macio_get_drvdata(mdev); + struct bmac_data *bp = dev->priv; unsigned long flags; unsigned short config; - struct net_device* dev = bmac_devs; int i; - if (bmac_devs == 0) - return PBOOK_SLEEP_OK; - - bp = (struct bmac_data *) dev->priv; - - switch (when) { - case PBOOK_SLEEP_REQUEST: - break; - case PBOOK_SLEEP_REJECT: - break; - case PBOOK_SLEEP_NOW: - netif_device_detach(dev); - /* prolly should wait for dma to finish & turn off the chip */ - spin_lock_irqsave(&bp->lock, flags); - if (bp->timeout_active) { - del_timer(&bp->tx_timeout); - bp->timeout_active = 0; - } - disable_irq(dev->irq); - disable_irq(bp->tx_dma_intr); - disable_irq(bp->rx_dma_intr); - bp->sleeping = 1; - spin_unlock_irqrestore(&bp->lock, flags); - if (bp->opened) { - volatile struct dbdma_regs *rd = bp->rx_dma; - volatile struct dbdma_regs *td = bp->tx_dma; + netif_device_detach(dev); + /* prolly should wait for dma to finish & turn off the chip */ + spin_lock_irqsave(&bp->lock, flags); + if (bp->timeout_active) { + del_timer(&bp->tx_timeout); + bp->timeout_active = 0; + } + disable_irq(dev->irq); + disable_irq(bp->tx_dma_intr); + disable_irq(bp->rx_dma_intr); + bp->sleeping = 1; + spin_unlock_irqrestore(&bp->lock, flags); + if (bp->opened) { + volatile struct dbdma_regs *rd = bp->rx_dma; + volatile struct dbdma_regs *td = bp->tx_dma; - config = bmread(dev, RXCFG); - bmwrite(dev, RXCFG, (config & ~RxMACEnable)); - config = bmread(dev, TXCFG); - bmwrite(dev, TXCFG, (config & ~TxMACEnable)); - bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */ - /* disable rx and tx dma */ - st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ - st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ - /* free some skb's */ - for (i=0; irx_bufs[i] != NULL) { - dev_kfree_skb(bp->rx_bufs[i]); - bp->rx_bufs[i] = NULL; - } - } - for (i = 0; itx_bufs[i] != NULL) { - dev_kfree_skb(bp->tx_bufs[i]); - bp->tx_bufs[i] = NULL; - } - } + config = bmread(dev, RXCFG); + bmwrite(dev, RXCFG, (config & ~RxMACEnable)); + config = bmread(dev, TXCFG); + bmwrite(dev, TXCFG, (config & ~TxMACEnable)); + bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */ + /* disable rx and tx dma */ + st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + /* free some skb's */ + for (i=0; irx_bufs[i] != NULL) { + dev_kfree_skb(bp->rx_bufs[i]); + bp->rx_bufs[i] = NULL; + } + } + for (i = 0; itx_bufs[i] != NULL) { + dev_kfree_skb(bp->tx_bufs[i]); + bp->tx_bufs[i] = NULL; + } } - pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); - break; - case PBOOK_WAKE: - /* see if this is enough */ - if (bp->opened) - bmac_reset_and_enable(dev); - enable_irq(dev->irq); - enable_irq(bp->tx_dma_intr); - enable_irq(bp->rx_dma_intr); - netif_device_attach(dev); - break; } - return PBOOK_SLEEP_OK; + pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0); + return 0; } -#endif + +static int bmac_resume(struct macio_dev *mdev) +{ + struct net_device* dev = macio_get_drvdata(mdev); + struct bmac_data *bp = dev->priv; + + /* see if this is enough */ + if (bp->opened) + bmac_reset_and_enable(dev); + + enable_irq(dev->irq); + enable_irq(bp->tx_dma_intr); + enable_irq(bp->rx_dma_intr); + netif_device_attach(dev); + + return 0; +} +#endif /* CONFIG_PM */ static int bmac_set_address(struct net_device *dev, void *addr) { @@ -1277,103 +1261,61 @@ static void bmac_reset_and_enable(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); } -static int __init bmac_probe(void) -{ - struct device_node *bmac; - - MOD_INC_USE_COUNT; - - for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next) - bmac_probe1(bmac, 0); - for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0; - bmac = bmac->next) - bmac_probe1(bmac, 1); - - if (bmac_devs != 0) { - proc_net_create ("bmac", 0, bmac_proc_info); -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier(&bmac_sleep_notifier); -#endif - } - - MOD_DEC_USE_COUNT; - - return bmac_devs? 0: -ENODEV; -} - -static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) +static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_match *match) { int j, rev, ret; struct bmac_data *bp; unsigned char *addr; struct net_device *dev; + int is_bmac_plus = ((int)match->data) != 0; - if (bmac->n_addrs != 3 || bmac->n_intrs != 3) { - printk(KERN_ERR "can't use BMAC %s: need 3 addrs and 3 intrs\n", - bmac->full_name); - return; + if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) { + printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n"); + return -ENODEV; } - addr = get_property(bmac, "mac-address", NULL); + addr = get_property(macio_get_of_node(mdev), "mac-address", NULL); if (addr == NULL) { - addr = get_property(bmac, "local-mac-address", NULL); + addr = get_property(macio_get_of_node(mdev), "local-mac-address", NULL); if (addr == NULL) { - printk(KERN_ERR "Can't get mac-address for BMAC %s\n", - bmac->full_name); - return; - } - } - - if (bmac_emergency_rxbuf == NULL) { - bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL); - if (bmac_emergency_rxbuf == NULL) { - printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n"); - return; + printk(KERN_ERR "BMAC: Can't get mac-address\n"); + return -ENODEV; } } dev = alloc_etherdev(PRIV_BYTES); if (!dev) { - printk(KERN_ERR "alloc_etherdev failed, out of memory for BMAC %s\n", - bmac->full_name); - return; + printk(KERN_ERR "BMAC: alloc_etherdev failed, out of memory\n"); + return -ENOMEM; } bp = (struct bmac_data *) dev->priv; SET_MODULE_OWNER(dev); - bp->node = bmac; + SET_NETDEV_DEV(dev, &mdev->ofdev.dev); + macio_set_drvdata(mdev, dev); + + bp->mdev = mdev; spin_lock_init(&bp->lock); - if (!request_OF_resource(bmac, 0, " (bmac)")) { + if (macio_request_resources(mdev, "bmac")) { printk(KERN_ERR "BMAC: can't request IO resource !\n"); - goto out1; - } - if (!request_OF_resource(bmac, 1, " (bmac tx dma)")) { - printk(KERN_ERR "BMAC: can't request TX DMA resource !\n"); - goto out2; - } - if (!request_OF_resource(bmac, 2, " (bmac rx dma)")) { - printk(KERN_ERR "BMAC: can't request RX DMA resource !\n"); - goto out3; + goto out_free; } dev->base_addr = (unsigned long) - ioremap(bmac->addrs[0].address, bmac->addrs[0].size); - if (!dev->base_addr) - goto out4; + ioremap(macio_resource_start(mdev, 0), macio_resource_len(mdev, 0)); + if (dev->base_addr == 0) + goto out_release; - dev->irq = bmac->intrs[0].line; + dev->irq = macio_irq(mdev, 0); bmac_enable_and_reset_chip(dev); bmwrite(dev, INTDISABLE, DisableAll); - printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": "")); rev = addr[0] == 0 && addr[1] == 0xA0; for (j = 0; j < 6; ++j) { dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]); } - XXDEBUG((", base_addr=%#0lx", dev->base_addr)); - printk("\n"); /* Enable chip without interrupts for now */ bmac_enable_and_reset_chip(dev); @@ -1392,15 +1334,15 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) bp->is_bmac_plus = is_bmac_plus; bp->tx_dma = (volatile struct dbdma_regs *) - ioremap(bmac->addrs[1].address, bmac->addrs[1].size); + ioremap(macio_resource_start(mdev, 1), macio_resource_len(mdev, 1)); if (!bp->tx_dma) goto err_out_iounmap; - bp->tx_dma_intr = bmac->intrs[1].line; + bp->tx_dma_intr = macio_irq(mdev, 1); bp->rx_dma = (volatile struct dbdma_regs *) - ioremap(bmac->addrs[2].address, bmac->addrs[2].size); + ioremap(macio_resource_start(mdev, 2), macio_resource_len(mdev, 2)); if (!bp->rx_dma) goto err_out_iounmap_tx; - bp->rx_dma_intr = bmac->intrs[2].line; + bp->rx_dma_intr = macio_irq(mdev, 2); bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1); bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1; @@ -1415,14 +1357,14 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq); goto err_out_iounmap_rx; } - ret = request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", dev); + ret = request_irq(bp->tx_dma_intr, bmac_txdma_intr, 0, "BMAC-txdma", dev); if (ret) { - printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line); + printk(KERN_ERR "BMAC: can't get irq %d\n", bp->tx_dma_intr); goto err_out_irq0; } - ret = request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", dev); + ret = request_irq(bp->rx_dma_intr, bmac_rxdma_intr, 0, "BMAC-rxdma", dev); if (ret) { - printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line); + printk(KERN_ERR "BMAC: can't get irq %d\n", bp->rx_dma_intr); goto err_out_irq1; } @@ -1430,22 +1372,23 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) * re-enabled on open() */ disable_irq(dev->irq); - pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); + pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0); if (register_netdev(dev) != 0) { - printk(KERN_ERR "registration failed for BMAC %s\n", - bmac->full_name); + printk(KERN_ERR "BMAC: Ethernet registration failed\n"); goto err_out_irq2; } + + printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": "")); + XXDEBUG((", base_addr=%#0lx", dev->base_addr)); + printk("\n"); - bp->next_bmac = bmac_devs; - bmac_devs = dev; - return; + return 0; err_out_irq2: - free_irq(bmac->intrs[2].line, dev); + free_irq(bp->rx_dma_intr, dev); err_out_irq1: - free_irq(bmac->intrs[1].line, dev); + free_irq(bp->tx_dma_intr, dev); err_out_irq0: free_irq(dev->irq, dev); err_out_iounmap_rx: @@ -1454,15 +1397,13 @@ err_out_iounmap_tx: iounmap((void *)bp->tx_dma); err_out_iounmap: iounmap((void *)dev->base_addr); -out4: - release_OF_resource(bp->node, 2); -out3: - release_OF_resource(bp->node, 1); -out2: - release_OF_resource(bp->node, 0); -out1: - pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); +out_release: + macio_release_resources(mdev); +out_free: + pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0); free_netdev(dev); + + return -ENODEV; } static int bmac_open(struct net_device *dev) @@ -1520,7 +1461,7 @@ static int bmac_close(struct net_device *dev) bp->opened = 0; disable_irq(dev->irq); - pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0); + pmac_call_feature(PMAC_FTR_BMAC_ENABLE, macio_get_of_node(bp->mdev), 0, 0); return 0; } @@ -1649,6 +1590,7 @@ static void dump_dbdma(volatile struct dbdma_cmd *cp,int count) } #endif +#if 0 static int bmac_proc_info(char *buffer, char **start, off_t offset, int length) { @@ -1683,46 +1625,86 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length) return len; } +#endif +static int __devexit bmac_remove(struct macio_dev *mdev) +{ + struct net_device *dev = macio_get_drvdata(mdev); + struct bmac_data *bp = dev->priv; -MODULE_AUTHOR("Randy Gobbel/Paul Mackerras"); -MODULE_DESCRIPTION("PowerMac BMAC ethernet driver."); -MODULE_LICENSE("GPL"); + unregister_netdev(dev); -static void __exit bmac_cleanup (void) -{ - struct bmac_data *bp; - struct net_device *dev; + free_irq(dev->irq, dev); + free_irq(bp->tx_dma_intr, dev); + free_irq(bp->rx_dma_intr, dev); - if (bmac_emergency_rxbuf != NULL) { - kfree(bmac_emergency_rxbuf); - bmac_emergency_rxbuf = NULL; - } + iounmap((void *)dev->base_addr); + iounmap((void *)bp->tx_dma); + iounmap((void *)bp->rx_dma); - if (bmac_devs == 0) - return; -#ifdef CONFIG_PMAC_PBOOK - pmu_unregister_sleep_notifier(&bmac_sleep_notifier); + macio_release_resources(mdev); + + free_netdev(dev); + + return 0; +} + +static struct of_match bmac_match[] = +{ + { + .name = "bmac", + .type = OF_ANY_MATCH, + .compatible = OF_ANY_MATCH, + .data = (void *)0, + }, + { + .name = OF_ANY_MATCH, + .type = "network", + .compatible = "bmac+", + .data = (void *)1, + }, + {}, +}; + +static struct macio_driver bmac_driver = +{ + .name = "bmac", + .match_table = bmac_match, + .probe = bmac_probe, + .remove = bmac_remove, +#ifdef CONFIG_PM + .suspend = bmac_suspend, + .resume = bmac_resume, #endif - proc_net_remove("bmac"); +}; - do { - dev = bmac_devs; - bp = (struct bmac_data *) dev->priv; - bmac_devs = bp->next_bmac; - unregister_netdev(dev); +static int __init bmac_init(void) +{ + if (bmac_emergency_rxbuf == NULL) { + bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL); + if (bmac_emergency_rxbuf == NULL) { + printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n"); + return -ENOMEM; + } + } - release_OF_resource(bp->node, 0); - release_OF_resource(bp->node, 1); - release_OF_resource(bp->node, 2); - free_irq(dev->irq, dev); - free_irq(bp->tx_dma_intr, dev); - free_irq(bp->rx_dma_intr, dev); + return macio_register_driver(&bmac_driver); +} - free_netdev(dev); - } while (bmac_devs != NULL); +static void __exit bmac_exit(void) +{ + macio_unregister_driver(&bmac_driver); + + if (bmac_emergency_rxbuf != NULL) { + kfree(bmac_emergency_rxbuf); + bmac_emergency_rxbuf = NULL; + } } -module_init(bmac_probe); -module_exit(bmac_cleanup); +MODULE_AUTHOR("Randy Gobbel/Paul Mackerras"); +MODULE_DESCRIPTION("PowerMac BMAC ethernet driver."); +MODULE_LICENSE("GPL"); + +module_init(bmac_init); +module_exit(bmac_exit); -- 2.53.0