diff -r 5801d4a4ff7d -r 2b949dcba32b devices/forcedeth-2.6.19-ethercat.c --- a/devices/forcedeth-2.6.19-ethercat.c Thu Feb 22 09:19:02 2007 +0000 +++ b/devices/forcedeth-2.6.19-ethercat.c Thu Feb 22 09:34:32 2007 +0000 @@ -2385,7 +2385,8 @@ struct fe_priv *np = netdev_priv(dev); if (np->ecdev) { - nv_update_linkspeed(dev); + int link = nv_update_linkspeed(dev); + ecdev_link_state(np->ecdev, link); return; } @@ -2441,19 +2442,19 @@ if (!(events & np->irqmask)) break; - spin_lock(&np->lock); + if (!np->ecdev) spin_lock(&np->lock); nv_tx_done(dev); - spin_unlock(&np->lock); + if (!np->ecdev) spin_unlock(&np->lock); if (events & NVREG_IRQ_LINK) { - spin_lock(&np->lock); + if (!np->ecdev) spin_lock(&np->lock); nv_link_irq(dev); - spin_unlock(&np->lock); + if (!np->ecdev) spin_unlock(&np->lock); } if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { - spin_lock(&np->lock); + if (!np->ecdev) spin_lock(&np->lock); nv_linkchange(dev); - spin_unlock(&np->lock); + if (!np->ecdev) spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } if (events & (NVREG_IRQ_TX_ERR)) { @@ -2466,21 +2467,26 @@ } #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { - netif_rx_schedule(dev); - - /* Disable furthur receive irq's */ - spin_lock(&np->lock); - np->irqmask &= ~NVREG_IRQ_RX_ALL; - - if (np->msi_flags & NV_MSI_X_ENABLED) - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - spin_unlock(&np->lock); + if (np->ecdev) { + nv_rx_process(dev, dev->weight); + } + else { + netif_rx_schedule(dev); + + /* Disable furthur receive irq's */ + spin_lock(&np->lock); + np->irqmask &= ~NVREG_IRQ_RX_ALL; + + if (np->msi_flags & NV_MSI_X_ENABLED) + writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); + spin_unlock(&np->lock); + } } #else nv_rx_process(dev, dev->weight); - if (nv_alloc_rx(dev)) { + if (nv_alloc_rx(dev) && !np->ecdev) { spin_lock(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); @@ -2488,20 +2494,22 @@ } #endif if (i > max_interrupt_work) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + if (!np->ecdev) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(0, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock(&np->lock); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); - spin_unlock(&np->lock); break; } @@ -2518,7 +2526,7 @@ u8 __iomem *base = get_hwbase(dev); u32 events; int i; - unsigned long flags; + unsigned long flags = 0; dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name); @@ -2530,26 +2538,28 @@ if (!(events & np->irqmask)) break; - spin_lock_irqsave(&np->lock, flags); + if (!np->ecdev) spin_lock_irqsave(&np->lock, flags); nv_tx_done(dev); - spin_unlock_irqrestore(&np->lock, flags); + if (!np->ecdev) spin_unlock_irqrestore(&np->lock, flags); if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); } if (i > max_interrupt_work) { - spin_lock_irqsave(&np->lock, flags); - /* disable interrupts on the nic */ - writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq |= NVREG_IRQ_TX_ALL; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + if (!np->ecdev) { + spin_lock_irqsave(&np->lock, flags); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_TX_ALL; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock_irqrestore(&np->lock, flags); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); - spin_unlock_irqrestore(&np->lock, flags); break; } @@ -2601,13 +2611,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) { struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); u32 events; events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); - if (events) { + if (events && !np->ecdev) { netif_rx_schedule(dev); /* disable receive interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); @@ -2636,7 +2647,7 @@ break; nv_rx_process(dev, dev->weight); - if (nv_alloc_rx(dev)) { + if (nv_alloc_rx(dev) && !np->ecdev) { spin_lock_irqsave(&np->lock, flags); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); @@ -2644,17 +2655,19 @@ } if (i > max_interrupt_work) { - spin_lock_irqsave(&np->lock, flags); - /* disable interrupts on the nic */ - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq |= NVREG_IRQ_RX_ALL; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + if (!np->ecdev) { + spin_lock_irqsave(&np->lock, flags); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_RX_ALL; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock_irqrestore(&np->lock, flags); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); - spin_unlock_irqrestore(&np->lock, flags); break; } } @@ -2671,7 +2684,7 @@ u8 __iomem *base = get_hwbase(dev); u32 events; int i; - unsigned long flags; + unsigned long flags = 0; dprintk(KERN_DEBUG "%s: nv_nic_irq_other\n", dev->name); @@ -2684,14 +2697,14 @@ break; if (events & NVREG_IRQ_LINK) { - spin_lock_irqsave(&np->lock, flags); + if (!np->ecdev) spin_lock_irqsave(&np->lock, flags); nv_link_irq(dev); - spin_unlock_irqrestore(&np->lock, flags); + if (!np->ecdev) spin_unlock_irqrestore(&np->lock, flags); } if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { - spin_lock_irqsave(&np->lock, flags); + if (!np->ecdev) spin_lock_irqsave(&np->lock, flags); nv_linkchange(dev); - spin_unlock_irqrestore(&np->lock, flags); + if (!np->ecdev) spin_unlock_irqrestore(&np->lock, flags); np->link_timeout = jiffies + LINK_TIMEOUT; } if (events & (NVREG_IRQ_UNKNOWN)) { @@ -2699,17 +2712,19 @@ dev->name, events); } if (i > max_interrupt_work) { - spin_lock_irqsave(&np->lock, flags); - /* disable interrupts on the nic */ - writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq |= NVREG_IRQ_OTHER; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + if (!np->ecdev) { + spin_lock_irqsave(&np->lock, flags); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_OTHER; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock_irqrestore(&np->lock, flags); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); - spin_unlock_irqrestore(&np->lock, flags); break; } @@ -2893,7 +2908,21 @@ void ec_poll(struct net_device *dev) { - nv_nic_irq(0, dev); + struct fe_priv *np = netdev_priv(dev); + + if (!using_multi_irqs(dev)) { + nv_nic_irq(0, dev); + } else { + if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { + nv_nic_irq_rx(0, dev); + } + if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { + nv_nic_irq_tx(0, dev); + } + if (np->nic_poll_irq & NVREG_IRQ_OTHER) { + nv_nic_irq_other(0, dev); + } + } } static void nv_do_nic_poll(unsigned long data) @@ -4158,14 +4187,17 @@ writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - if (nv_request_irq(dev, 0)) { - goto out_drain; - } - - /* ask for interrupts */ - nv_enable_hw_interrupts(dev, np->irqmask); - - spin_lock_irq(&np->lock); + if (!np->ecdev) { + if (nv_request_irq(dev, 0)) { + goto out_drain; + } + + /* ask for interrupts */ + nv_enable_hw_interrupts(dev, np->irqmask); + + spin_lock_irq(&np->lock); + } + writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); writel(0, base + NvRegMulticastAddrB); writel(0, base + NvRegMulticastMaskA); @@ -4186,23 +4218,29 @@ ret = nv_update_linkspeed(dev); nv_start_rx(dev); nv_start_tx(dev); - netif_start_queue(dev); - netif_poll_enable(dev); - - if (ret) { - netif_carrier_on(dev); - } else { - printk("%s: no link during initialization.\n", dev->name); - netif_carrier_off(dev); - } - if (oom) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - - /* start statistics timer */ - if (np->driver_data & DEV_HAS_STATISTICS) - mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); - - spin_unlock_irq(&np->lock); + + if (np->ecdev) { + ecdev_link_state(np->ecdev, ret); + } + else { + netif_start_queue(dev); + netif_poll_enable(dev); + + if (ret) { + netif_carrier_on(dev); + } else { + printk("%s: no link during initialization.\n", dev->name); + netif_carrier_off(dev); + } + if (oom) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + + /* start statistics timer */ + if (np->driver_data & DEV_HAS_STATISTICS) + mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); + + spin_unlock_irq(&np->lock); + } return 0; out_drain: @@ -4215,31 +4253,36 @@ struct fe_priv *np = netdev_priv(dev); u8 __iomem *base; - spin_lock_irq(&np->lock); - np->in_shutdown = 1; - spin_unlock_irq(&np->lock); - netif_poll_disable(dev); - synchronize_irq(dev->irq); - - del_timer_sync(&np->oom_kick); - del_timer_sync(&np->nic_poll); - del_timer_sync(&np->stats_poll); - - netif_stop_queue(dev); - spin_lock_irq(&np->lock); + if (!np->ecdev) { + spin_lock_irq(&np->lock); + np->in_shutdown = 1; + spin_unlock_irq(&np->lock); + netif_poll_disable(dev); + synchronize_irq(dev->irq); + + del_timer_sync(&np->oom_kick); + del_timer_sync(&np->nic_poll); + del_timer_sync(&np->stats_poll); + + netif_stop_queue(dev); + spin_lock_irq(&np->lock); + } + nv_stop_tx(dev); nv_stop_rx(dev); nv_txrx_reset(dev); /* disable interrupts on the nic or we will lock up */ base = get_hwbase(dev); - nv_disable_hw_interrupts(dev, np->irqmask); + if (!np->ecdev) nv_disable_hw_interrupts(dev, np->irqmask); pci_push(base); dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); - spin_unlock_irq(&np->lock); - - nv_free_irq(dev); + if (!np->ecdev) { + spin_unlock_irq(&np->lock); + + nv_free_irq(dev); + } drain_ring(dev); @@ -4585,13 +4628,19 @@ np->autoneg = 1; // offer device to EtherCAT master module - if (ecdev_offer(dev, &np->ecdev, "forcedeth", board_idx, - ec_poll, THIS_MODULE)) { + if (ecdev_offer(dev, &np->ecdev, "forcedeth", board_idx, ec_poll, + THIS_MODULE)) { printk(KERN_ERR "forcedeth: Failed to offer device.\n"); goto out_error; } - if (!np->ecdev) { + if (np->ecdev) { + if (ecdev_open(np->ecdev)) { + ecdev_withdraw(np->ecdev); + goto out_error; + } + } + else { err = register_netdev(dev); if (err) { printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err); @@ -4755,7 +4804,9 @@ static int __init init_nic(void) { - printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION); + printk(KERN_INFO "forcedeth: EtherCAT-capable nForce ethernet driver." + " Version %s, master %s.\n", + FORCEDETH_VERSION, EC_MASTER_VERSION); return pci_register_driver(&driver); } @@ -4777,8 +4828,8 @@ module_param(dma_64bit, int, 0); MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); -MODULE_AUTHOR("Manfred Spraul "); -MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); +MODULE_AUTHOR("Dipl.-Ing. (FH) Florian Pose "); +MODULE_DESCRIPTION("EtherCAT-capable nForce ethernet driver"); MODULE_LICENSE("GPL"); //MODULE_DEVICE_TABLE(pci, pci_tbl); // prevent auto-loading