From 3c36a837a960ccbff05fa773a495c389fbd42f0e Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Wed, 26 Nov 2008 22:59:18 +0100 Subject: IXP4xx: Silence section mismatch warning in Ethernet driver. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/ixp4xx_eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 14ffa2a61890..e6e4004b13bb 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -1231,7 +1231,7 @@ static int __devexit eth_remove_one(struct platform_device *pdev) return 0; } -static struct platform_driver drv = { +static struct platform_driver ixp4xx_eth_driver = { .driver.name = DRV_NAME, .probe = eth_init_one, .remove = eth_remove_one, @@ -1247,12 +1247,12 @@ static int __init eth_init_module(void) mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); - return platform_driver_register(&drv); + return platform_driver_register(&ixp4xx_eth_driver); } static void __exit eth_cleanup_module(void) { - platform_driver_unregister(&drv); + platform_driver_unregister(&ixp4xx_eth_driver); } MODULE_AUTHOR("Krzysztof Halasa"); -- cgit v1.2.3 From b4c7d3b07257528d3c0bfd07c5b38b48beb9b6d1 Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Sat, 20 Dec 2008 01:58:59 +0100 Subject: IXP4xx: Make the Ethernet driver use built-in netdev stats. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/ixp4xx_eth.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index e6e4004b13bb..44679f804be3 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -164,7 +164,6 @@ struct port { struct npe *npe; struct net_device *netdev; struct napi_struct napi; - struct net_device_stats stat; struct mii_if_info mii; struct delayed_work mdio_thread; struct eth_plat_info *plat; @@ -562,7 +561,7 @@ static int eth_poll(struct napi_struct *napi, int budget) #endif if (!skb) { - port->stat.rx_dropped++; + dev->stats.rx_dropped++; /* put the desc back on RX-ready queue */ desc->buf_len = MAX_MRU; desc->pkt_len = 0; @@ -588,8 +587,8 @@ static int eth_poll(struct napi_struct *napi, int budget) debug_pkt(dev, "eth_poll", skb->data, skb->len); skb->protocol = eth_type_trans(skb, dev); - port->stat.rx_packets++; - port->stat.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; netif_receive_skb(skb); /* put the new buffer on RX-free queue */ @@ -634,8 +633,8 @@ static void eth_txdone_irq(void *unused) debug_desc(phys, desc); if (port->tx_buff_tab[n_desc]) { /* not the draining packet */ - port->stat.tx_packets++; - port->stat.tx_bytes += desc->pkt_len; + port->netdev->stats.tx_packets++; + port->netdev->stats.tx_bytes += desc->pkt_len; dma_unmap_tx(port, desc); #if DEBUG_TX @@ -673,7 +672,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb->len > MAX_MRU)) { dev_kfree_skb(skb); - port->stat.tx_errors++; + dev->stats.tx_errors++; return NETDEV_TX_OK; } @@ -689,7 +688,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) bytes = ALIGN(offset + len, 4); if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { dev_kfree_skb(skb); - port->stat.tx_dropped++; + dev->stats.tx_dropped++; return NETDEV_TX_OK; } memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); @@ -703,7 +702,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) #else kfree(mem); #endif - port->stat.tx_dropped++; + dev->stats.tx_dropped++; return NETDEV_TX_OK; } @@ -746,12 +745,6 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) } -static struct net_device_stats *eth_stats(struct net_device *dev) -{ - struct port *port = netdev_priv(dev); - return &port->stat; -} - static void eth_set_mcast_list(struct net_device *dev) { struct port *port = netdev_priv(dev); @@ -1155,7 +1148,6 @@ static int __devinit eth_init_one(struct platform_device *pdev) dev->open = eth_open; dev->hard_start_xmit = eth_xmit; dev->stop = eth_close; - dev->get_stats = eth_stats; dev->do_ioctl = eth_ioctl; dev->set_multicast_list = eth_set_mcast_list; dev->tx_queue_len = 100; -- cgit v1.2.3 From 2098c18d6cf65358dd1620154bdedbc8c8d36f44 Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Sat, 20 Dec 2008 01:53:08 +0100 Subject: IXP4xx: Add PHYLIB support to Ethernet driver. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/Kconfig | 2 +- drivers/net/arm/ixp4xx_eth.c | 194 +++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 100 deletions(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index abe17762e6f5..2895db13bfa4 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -59,7 +59,7 @@ config EP93XX_ETH config IXP4XX_ETH tristate "Intel IXP4xx Ethernet support" depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR - select MII + select PHYLIB help Say Y here if you want to use built-in Ethernet ports on IXP4xx processor. diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 44679f804be3..db44ebbf45c5 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -59,7 +59,6 @@ #define NAPI_WEIGHT 16 #define MDIO_INTERVAL (3 * HZ) #define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */ -#define MAX_MII_RESET_RETRIES 100 /* mdio_read() cycles, typically 4 */ #define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */ #define NPE_ID(port_id) ((port_id) >> 4) @@ -164,14 +163,13 @@ struct port { struct npe *npe; struct net_device *netdev; struct napi_struct napi; - struct mii_if_info mii; - struct delayed_work mdio_thread; + struct phy_device *phydev; struct eth_plat_info *plat; buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; struct desc *desc_tab; /* coherent */ u32 desc_tab_phys; int id; /* logical port ID */ - u16 mii_bmcr; + int speed, duplex; }; /* NPE message structure */ @@ -242,19 +240,20 @@ static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) static spinlock_t mdio_lock; static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */ +struct mii_bus *mdio_bus; static int ports_open; static struct port *npe_port_tab[MAX_NPES]; static struct dma_pool *dma_pool; -static u16 mdio_cmd(struct net_device *dev, int phy_id, int location, - int write, u16 cmd) +static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, + int write, u16 cmd) { int cycles = 0; if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) { - printk(KERN_ERR "%s: MII not ready to transmit\n", dev->name); - return 0; + printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name); + return -1; } if (write) { @@ -273,107 +272,119 @@ static u16 mdio_cmd(struct net_device *dev, int phy_id, int location, } if (cycles == MAX_MDIO_RETRIES) { - printk(KERN_ERR "%s: MII write failed\n", dev->name); - return 0; + printk(KERN_ERR "%s #%i: MII write failed\n", bus->name, + phy_id); + return -1; } #if DEBUG_MDIO - printk(KERN_DEBUG "%s: mdio_cmd() took %i cycles\n", dev->name, - cycles); + printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name, + phy_id, write ? "write" : "read", cycles); #endif if (write) return 0; if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) { - printk(KERN_ERR "%s: MII read failed\n", dev->name); - return 0; +#if DEBUG_MDIO + printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name, + phy_id); +#endif + return 0xFFFF; /* don't return error */ } return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) | - (__raw_readl(&mdio_regs->mdio_status[1]) << 8); + ((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8); } -static int mdio_read(struct net_device *dev, int phy_id, int location) +static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location) { unsigned long flags; - u16 val; + int ret; spin_lock_irqsave(&mdio_lock, flags); - val = mdio_cmd(dev, phy_id, location, 0, 0); + ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0); spin_unlock_irqrestore(&mdio_lock, flags); - return val; +#if DEBUG_MDIO + printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name, + phy_id, location, ret); +#endif + return ret; } -static void mdio_write(struct net_device *dev, int phy_id, int location, - int val) +static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location, + u16 val) { unsigned long flags; + int ret; spin_lock_irqsave(&mdio_lock, flags); - mdio_cmd(dev, phy_id, location, 1, val); + ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val); spin_unlock_irqrestore(&mdio_lock, flags); +#if DEBUG_MDIO + printk(KERN_DEBUG "%s #%i: MII read [%i] <- 0x%X, err = %i\n", + bus->name, phy_id, location, val, ret); +#endif + return ret; } -static void phy_reset(struct net_device *dev, int phy_id) +static int ixp4xx_mdio_register(void) { - struct port *port = netdev_priv(dev); - int cycles = 0; + int err; + + if (!(mdio_bus = mdiobus_alloc())) + return -ENOMEM; - mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET); + /* All MII PHY accesses use NPE-B Ethernet registers */ + spin_lock_init(&mdio_lock); + mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; + __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); - while (cycles < MAX_MII_RESET_RETRIES) { - if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) { -#if DEBUG_MDIO - printk(KERN_DEBUG "%s: phy_reset() took %i cycles\n", - dev->name, cycles); -#endif - return; - } - udelay(1); - cycles++; - } + mdio_bus->name = "IXP4xx MII Bus"; + mdio_bus->read = &ixp4xx_mdio_read; + mdio_bus->write = &ixp4xx_mdio_write; + strcpy(mdio_bus->id, "0"); - printk(KERN_ERR "%s: MII reset failed\n", dev->name); + if ((err = mdiobus_register(mdio_bus))) + mdiobus_free(mdio_bus); + return err; } -static void eth_set_duplex(struct port *port) +static void ixp4xx_mdio_remove(void) { - if (port->mii.full_duplex) - __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, - &port->regs->tx_control[0]); - else - __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, - &port->regs->tx_control[0]); + mdiobus_unregister(mdio_bus); + mdiobus_free(mdio_bus); } -static void phy_check_media(struct port *port, int init) +static void ixp4xx_adjust_link(struct net_device *dev) { - if (mii_check_media(&port->mii, 1, init)) - eth_set_duplex(port); - if (port->mii.force_media) { /* mii_check_media() doesn't work */ - struct net_device *dev = port->netdev; - int cur_link = mii_link_ok(&port->mii); - int prev_link = netif_carrier_ok(dev); - - if (!prev_link && cur_link) { - printk(KERN_INFO "%s: link up\n", dev->name); - netif_carrier_on(dev); - } else if (prev_link && !cur_link) { + struct port *port = netdev_priv(dev); + struct phy_device *phydev = port->phydev; + + if (!phydev->link) { + if (port->speed) { + port->speed = 0; printk(KERN_INFO "%s: link down\n", dev->name); - netif_carrier_off(dev); } + return; } -} + if (port->speed == phydev->speed && port->duplex == phydev->duplex) + return; -static void mdio_thread(struct work_struct *work) -{ - struct port *port = container_of(work, struct port, mdio_thread.work); + port->speed = phydev->speed; + port->duplex = phydev->duplex; - phy_check_media(port, 0); - schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL); + if (port->duplex) + __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + else + __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + + printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", + dev->name, port->speed, port->duplex ? "full" : "half"); } @@ -777,16 +788,9 @@ static void eth_set_mcast_list(struct net_device *dev) static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { - struct port *port = netdev_priv(dev); - unsigned int duplex_chg; - int err; - if (!netif_running(dev)) return -EINVAL; - err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg); - if (duplex_chg) - eth_set_duplex(port); - return err; + return -EINVAL; } @@ -938,8 +942,6 @@ static int eth_open(struct net_device *dev) } } - mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr); - memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_VLAN_SETRXQOSENTRY; msg.eth_id = port->id; @@ -977,6 +979,9 @@ static int eth_open(struct net_device *dev) return err; } + port->speed = 0; /* force "link up" message */ + phy_start(port->phydev); + for (i = 0; i < ETH_ALEN; i++) __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); __raw_writel(0x08, &port->regs->random_seed); @@ -1004,10 +1009,8 @@ static int eth_open(struct net_device *dev) __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]); napi_enable(&port->napi); - phy_check_media(port, 1); eth_set_mcast_list(dev); netif_start_queue(dev); - schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL); qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY, eth_rx_irq, dev); @@ -1098,14 +1101,10 @@ static int eth_close(struct net_device *dev) printk(KERN_CRIT "%s: unable to disable loopback\n", dev->name); - port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) & - ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */ - mdio_write(dev, port->plat->phy, MII_BMCR, - port->mii_bmcr | BMCR_PDOWN); + phy_stop(port->phydev); if (!ports_open) qmgr_disable_irq(TXDONE_QUEUE); - cancel_rearming_delayed_work(&port->mdio_thread); destroy_queues(port); release_queues(port); return 0; @@ -1117,6 +1116,7 @@ static int __devinit eth_init_one(struct platform_device *pdev) struct net_device *dev; struct eth_plat_info *plat = pdev->dev.platform_data; u32 regs_phys; + char phy_id[BUS_ID_SIZE]; int err; if (!(dev = alloc_etherdev(sizeof(struct port)))) @@ -1182,22 +1182,19 @@ static int __devinit eth_init_one(struct platform_device *pdev) __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); udelay(50); - port->mii.dev = dev; - port->mii.mdio_read = mdio_read; - port->mii.mdio_write = mdio_write; - port->mii.phy_id = plat->phy; - port->mii.phy_id_mask = 0x1F; - port->mii.reg_num_mask = 0x1F; + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); + port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(port->phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(port->phydev); + } + + port->phydev->irq = PHY_POLL; printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, npe_name(port->npe)); - phy_reset(dev, plat->phy); - port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) & - ~(BMCR_RESET | BMCR_PDOWN); - mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN); - - INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread); return 0; err_unreg: @@ -1231,20 +1228,19 @@ static struct platform_driver ixp4xx_eth_driver = { static int __init eth_init_module(void) { + int err; if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) return -ENOSYS; - /* All MII PHY accesses use NPE-B Ethernet registers */ - spin_lock_init(&mdio_lock); - mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; - __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); - + if ((err = ixp4xx_mdio_register())) + return err; return platform_driver_register(&ixp4xx_eth_driver); } static void __exit eth_cleanup_module(void) { platform_driver_unregister(&ixp4xx_eth_driver); + ixp4xx_mdio_remove(); } MODULE_AUTHOR("Krzysztof Halasa"); -- cgit v1.2.3 From 4954936e25cb8ce99a96cac9dd9417d7b639867a Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Sat, 20 Dec 2008 18:57:23 +0100 Subject: IXP4xx: Add PHYLIB MII ioctl to the Ethernet driver. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/ixp4xx_eth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index db44ebbf45c5..1bbb7b8cb0da 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -788,9 +788,11 @@ static void eth_set_mcast_list(struct net_device *dev) static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { + struct port *port = netdev_priv(dev); + if (!netif_running(dev)) return -EINVAL; - return -EINVAL; + return phy_mii_ioctl(port->phydev, if_mii(req), cmd); } -- cgit v1.2.3 From 490b77224fe66c77ab7cb48d6b77e62cb55591a0 Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Sun, 21 Dec 2008 00:02:34 +0100 Subject: IXP4xx: Add ethtool support to Ethernet driver. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/ixp4xx_eth.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 1bbb7b8cb0da..3f72eb66e7f1 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -170,6 +170,7 @@ struct port { u32 desc_tab_phys; int id; /* logical port ID */ int speed, duplex; + u8 firmware[4]; }; /* NPE message structure */ @@ -795,6 +796,45 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) return phy_mii_ioctl(port->phydev, if_mii(req), cmd); } +/* ethtool support */ + +static void ixp4xx_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct port *port = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u", + port->firmware[0], port->firmware[1], + port->firmware[2], port->firmware[3]); + strcpy(info->bus_info, "internal"); +} + +static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct port *port = netdev_priv(dev); + return phy_ethtool_gset(port->phydev, cmd); +} + +static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct port *port = netdev_priv(dev); + return phy_ethtool_sset(port->phydev, cmd); +} + +static int ixp4xx_nway_reset(struct net_device *dev) +{ + struct port *port = netdev_priv(dev); + return phy_start_aneg(port->phydev); +} + +static struct ethtool_ops ixp4xx_ethtool_ops = { + .get_drvinfo = ixp4xx_get_drvinfo, + .get_settings = ixp4xx_get_settings, + .set_settings = ixp4xx_set_settings, + .nway_reset = ixp4xx_nway_reset, + .get_link = ethtool_op_get_link, +}; + static int request_queues(struct port *port) { @@ -942,6 +982,10 @@ static int eth_open(struct net_device *dev) npe_name(npe)); return -EIO; } + port->firmware[0] = msg.byte4; + port->firmware[1] = msg.byte5; + port->firmware[2] = msg.byte6; + port->firmware[3] = msg.byte7; } memset(&msg, 0, sizeof(msg)); @@ -1151,6 +1195,7 @@ static int __devinit eth_init_one(struct platform_device *pdev) dev->hard_start_xmit = eth_xmit; dev->stop = eth_close; dev->do_ioctl = eth_ioctl; + dev->ethtool_ops = &ixp4xx_ethtool_ops; dev->set_multicast_list = eth_set_mcast_list; dev->tx_queue_len = 100; -- cgit v1.2.3 From e6da96ace859dad966fe85cc9552b89f48bbc930 Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Mon, 22 Dec 2008 00:26:38 +0100 Subject: IXP4xx: move common debugging from network drivers to QMGR module. Signed-off-by: Krzysztof Hałasa --- arch/arm/mach-ixp4xx/include/mach/qmgr.h | 35 ++++++++++++++++++-- arch/arm/mach-ixp4xx/ixp4xx_qmgr.c | 41 +++++++++++++++++------- drivers/net/arm/ixp4xx_eth.c | 55 +++++++------------------------- drivers/net/wan/ixp4xx_hss.c | 54 +++++++------------------------ 4 files changed, 85 insertions(+), 100 deletions(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h index 1e52b95cede5..0cbe6ceb67c5 100644 --- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h +++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h @@ -12,6 +12,8 @@ #include #include +#define DEBUG_QMGR 0 + #define HALF_QUEUES 32 #define QUEUES 64 /* only 32 lower queues currently supported */ #define MAX_QUEUE_LENGTH 4 /* in dwords */ @@ -61,22 +63,51 @@ void qmgr_enable_irq(unsigned int queue); void qmgr_disable_irq(unsigned int queue); /* request_ and release_queue() must be called from non-IRQ context */ + +#if DEBUG_QMGR +extern char qmgr_queue_descs[QUEUES][32]; + int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark); + unsigned int nearly_full_watermark, + const char *desc_format, const char* name); +#else +int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, + unsigned int nearly_empty_watermark, + unsigned int nearly_full_watermark); +#define qmgr_request_queue(queue, len, nearly_empty_watermark, \ + nearly_full_watermark, desc_format, name) \ + __qmgr_request_queue(queue, len, nearly_empty_watermark, \ + nearly_full_watermark) +#endif + void qmgr_release_queue(unsigned int queue); static inline void qmgr_put_entry(unsigned int queue, u32 val) { extern struct qmgr_regs __iomem *qmgr_regs; +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) put %X\n", + qmgr_queue_descs[queue], queue, val); +#endif __raw_writel(val, &qmgr_regs->acc[queue][0]); } static inline u32 qmgr_get_entry(unsigned int queue) { + u32 val; extern struct qmgr_regs __iomem *qmgr_regs; - return __raw_readl(&qmgr_regs->acc[queue][0]); + val = __raw_readl(&qmgr_regs->acc[queue][0]); +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) get %X\n", + qmgr_queue_descs[queue], queue, val); +#endif + return val; } static inline int qmgr_get_stat1(unsigned int queue) diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c index 444c2ae21db4..bfddc73d0a20 100644 --- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c +++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c @@ -14,8 +14,6 @@ #include #include -#define DEBUG 0 - struct qmgr_regs __iomem *qmgr_regs; static struct resource *mem_res; static spinlock_t qmgr_lock; @@ -23,6 +21,10 @@ static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ static void (*irq_handlers[HALF_QUEUES])(void *pdev); static void *irq_pdevs[HALF_QUEUES]; +#if DEBUG_QMGR +char qmgr_queue_descs[QUEUES][32]; +#endif + void qmgr_set_irq(unsigned int queue, int src, void (*handler)(void *pdev), void *pdev) { @@ -82,9 +84,16 @@ static inline void shift_mask(u32 *mask) mask[0] <<= 1; } +#if DEBUG_QMGR int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark) + unsigned int nearly_full_watermark, + const char *desc_format, const char* name) +#else +int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, + unsigned int nearly_empty_watermark, + unsigned int nearly_full_watermark) +#endif { u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ int err; @@ -152,12 +161,13 @@ int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, used_sram_bitmap[2] |= mask[2]; used_sram_bitmap[3] |= mask[3]; __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]); - spin_unlock_irq(&qmgr_lock); - -#if DEBUG - printk(KERN_DEBUG "qmgr: requested queue %i, addr = 0x%02X\n", - queue, addr); +#if DEBUG_QMGR + snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]), + desc_format, name); + printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n", + qmgr_queue_descs[queue], queue, addr); #endif + spin_unlock_irq(&qmgr_lock); return 0; err: @@ -190,6 +200,11 @@ void qmgr_release_queue(unsigned int queue) while (addr--) shift_mask(mask); +#if DEBUG_QMGR + printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n", + qmgr_queue_descs[queue], queue); + qmgr_queue_descs[queue][0] = '\x0'; +#endif __raw_writel(0, &qmgr_regs->sram[queue]); used_sram_bitmap[0] &= ~mask[0]; @@ -202,11 +217,8 @@ void qmgr_release_queue(unsigned int queue) module_put(THIS_MODULE); while ((addr = qmgr_get_entry(queue))) - printk(KERN_ERR "qmgr: released queue %d not empty: 0x%08X\n", + printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", queue, addr); -#if DEBUG - printk(KERN_DEBUG "qmgr: released queue %i\n", queue); -#endif } static int qmgr_init(void) @@ -277,5 +289,10 @@ EXPORT_SYMBOL(qmgr_regs); EXPORT_SYMBOL(qmgr_set_irq); EXPORT_SYMBOL(qmgr_enable_irq); EXPORT_SYMBOL(qmgr_disable_irq); +#if DEBUG_QMGR +EXPORT_SYMBOL(qmgr_queue_descs); EXPORT_SYMBOL(qmgr_request_queue); +#else +EXPORT_SYMBOL(__qmgr_request_queue); +#endif EXPORT_SYMBOL(qmgr_release_queue); diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 3f72eb66e7f1..64adf6cc1221 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -35,7 +35,6 @@ #include #include -#define DEBUG_QUEUES 0 #define DEBUG_DESC 0 #define DEBUG_RX 0 #define DEBUG_TX 0 @@ -423,47 +422,13 @@ static inline void debug_desc(u32 phys, struct desc *desc) #endif } -static inline void debug_queue(unsigned int queue, int is_get, u32 phys) -{ -#if DEBUG_QUEUES - static struct { - int queue; - char *name; - } names[] = { - { TX_QUEUE(0x10), "TX#0 " }, - { TX_QUEUE(0x20), "TX#1 " }, - { TX_QUEUE(0x00), "TX#2 " }, - { RXFREE_QUEUE(0x10), "RX-free#0 " }, - { RXFREE_QUEUE(0x20), "RX-free#1 " }, - { RXFREE_QUEUE(0x00), "RX-free#2 " }, - { TXDONE_QUEUE, "TX-done " }, - }; - int i; - - for (i = 0; i < ARRAY_SIZE(names); i++) - if (names[i].queue == queue) - break; - - printk(KERN_DEBUG "Queue %i %s%s %X\n", queue, - i < ARRAY_SIZE(names) ? names[i].name : "", - is_get ? "->" : "<-", phys); -#endif -} - -static inline u32 queue_get_entry(unsigned int queue) -{ - u32 phys = qmgr_get_entry(queue); - debug_queue(queue, 1, phys); - return phys; -} - static inline int queue_get_desc(unsigned int queue, struct port *port, int is_tx) { u32 phys, tab_phys, n_desc; struct desc *tab; - if (!(phys = queue_get_entry(queue))) + if (!(phys = qmgr_get_entry(queue))) return -1; phys &= ~0x1F; /* mask out non-address bits */ @@ -479,7 +444,6 @@ static inline int queue_get_desc(unsigned int queue, struct port *port, static inline void queue_put_desc(unsigned int queue, u32 phys, struct desc *desc) { - debug_queue(queue, 0, phys); debug_desc(phys, desc); BUG_ON(phys & 0x1F); qmgr_put_entry(queue, phys); @@ -628,7 +592,7 @@ static void eth_txdone_irq(void *unused) #if DEBUG_TX printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n"); #endif - while ((phys = queue_get_entry(TXDONE_QUEUE)) != 0) { + while ((phys = qmgr_get_entry(TXDONE_QUEUE)) != 0) { u32 npe_id, n_desc; struct port *port; struct desc *desc; @@ -840,25 +804,30 @@ static int request_queues(struct port *port) { int err; - err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0); + err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, + "%s:RX-free", port->netdev->name); if (err) return err; - err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0); + err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, + "%s:RX", port->netdev->name); if (err) goto rel_rxfree; - err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0); + err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, + "%s:TX", port->netdev->name); if (err) goto rel_rx; - err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0); + err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, + "%s:TX-ready", port->netdev->name); if (err) goto rel_tx; /* TX-done queue handles skbs sent out by the NPEs */ if (!ports_open) { - err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0); + err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, + "%s:TX-done", DRV_NAME); if (err) goto rel_txready; } diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index fa3ce81f4cfc..0c6802507a79 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -21,7 +21,6 @@ #include #include -#define DEBUG_QUEUES 0 #define DEBUG_DESC 0 #define DEBUG_RX 0 #define DEBUG_TX 0 @@ -555,48 +554,13 @@ static inline void debug_desc(u32 phys, struct desc *desc) #endif } -static inline void debug_queue(unsigned int queue, int is_get, u32 phys) -{ -#if DEBUG_QUEUES - static struct { - int queue; - char *name; - } names[] = { - { HSS0_PKT_TX0_QUEUE, "TX#0 " }, - { HSS0_PKT_TXDONE_QUEUE, "TX-done#0 " }, - { HSS0_PKT_RX_QUEUE, "RX#0 " }, - { HSS0_PKT_RXFREE0_QUEUE, "RX-free#0 " }, - { HSS1_PKT_TX0_QUEUE, "TX#1 " }, - { HSS1_PKT_TXDONE_QUEUE, "TX-done#1 " }, - { HSS1_PKT_RX_QUEUE, "RX#1 " }, - { HSS1_PKT_RXFREE0_QUEUE, "RX-free#1 " }, - }; - int i; - - for (i = 0; i < ARRAY_SIZE(names); i++) - if (names[i].queue == queue) - break; - - printk(KERN_DEBUG "Queue %i %s%s %X\n", queue, - i < ARRAY_SIZE(names) ? names[i].name : "", - is_get ? "->" : "<-", phys); -#endif -} - -static inline u32 queue_get_entry(unsigned int queue) -{ - u32 phys = qmgr_get_entry(queue); - debug_queue(queue, 1, phys); - return phys; -} - static inline int queue_get_desc(unsigned int queue, struct port *port, int is_tx) { u32 phys, tab_phys, n_desc; struct desc *tab; - if (!(phys = queue_get_entry(queue))) + if (!(phys = qmgr_get_entry(queue))) return -1; BUG_ON(phys & 0x1F); @@ -612,7 +576,6 @@ static inline int queue_get_desc(unsigned int queue, struct port *port, static inline void queue_put_desc(unsigned int queue, u32 phys, struct desc *desc) { - debug_queue(queue, 0, phys); debug_desc(phys, desc); BUG_ON(phys & 0x1F); qmgr_put_entry(queue, phys); @@ -930,23 +893,28 @@ static int request_hdlc_queues(struct port *port) { int err; - err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0); + err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0, + "%s:RX-free", port->netdev->name); if (err) return err; - err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0); + err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0, + "%s:RX", port->netdev->name); if (err) goto rel_rxfree; - err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0); + err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0, + "%s:TX", port->netdev->name); if (err) goto rel_rx; - err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0); + err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, + "%s:TX-ready", port->netdev->name); if (err) goto rel_tx; - err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0); + err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0, + "%s:TX-done", port->netdev->name); if (err) goto rel_txready; return 0; -- cgit v1.2.3 From 59f8500efb05096484a55263109acab6a6df89d5 Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Mon, 22 Dec 2008 02:00:17 +0100 Subject: Convert ixp4xx_eth driver to use net_device_ops. Signed-off-by: Krzysztof Hałasa --- drivers/net/arm/ixp4xx_eth.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net/arm/ixp4xx_eth.c') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 64adf6cc1221..1c757b6781bb 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -1125,6 +1125,15 @@ static int eth_close(struct net_device *dev) return 0; } +static const struct net_device_ops ixp4xx_netdev_ops = { + .ndo_open = eth_open, + .ndo_stop = eth_close, + .ndo_start_xmit = eth_xmit, + .ndo_set_multicast_list = eth_set_mcast_list, + .ndo_do_ioctl = eth_ioctl, + +}; + static int __devinit eth_init_one(struct platform_device *pdev) { struct port *port; @@ -1160,12 +1169,8 @@ static int __devinit eth_init_one(struct platform_device *pdev) goto err_free; } - dev->open = eth_open; - dev->hard_start_xmit = eth_xmit; - dev->stop = eth_close; - dev->do_ioctl = eth_ioctl; + dev->netdev_ops = &ixp4xx_netdev_ops; dev->ethtool_ops = &ixp4xx_ethtool_ops; - dev->set_multicast_list = eth_set_mcast_list; dev->tx_queue_len = 100; netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT); -- cgit v1.2.3