From 70cb92539cd1b8e1dec935a68fc154ea0db3a177 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 9 Jan 2009 13:14:07 -0800 Subject: mlx4_core: Fix warning from min() Recent cpumask changes changed num_possible_cpus() from returning an int to returning an unsigned int. This means that doing min(num_possible_cpus(), ) now produces a warning like drivers/net/mlx4/main.c: In function 'mlx4_enable_msi_x': drivers/net/mlx4/main.c:915: warning: comparison of distinct pointer types lacks a cast Fix this by using min_t(int, ...). Signed-off-by: Roland Dreier --- drivers/net/mlx4/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 710c79e7a2db..6ef2490d5c3e 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -912,8 +912,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs, - num_possible_cpus() + 1); + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + num_possible_cpus() + 1); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) goto no_msi; -- cgit v1.2.3 From 216c32d4407ea6951d6832773fdb3de058e12c62 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 8 Jan 2009 16:42:08 -0800 Subject: irda: fix incomplete conversation to internal stats Fix for commit af0490810c (irda: convert to internal stats) Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/au1k_ir.c | 2 +- drivers/net/irda/donauboe.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 75a1d0a86dee..941164076a2b 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -594,7 +594,7 @@ static int au1k_irda_rx(struct net_device *dev) update_rx_stats(dev, flags, count); skb=alloc_skb(count+1,GFP_ATOMIC); if (skb == NULL) { - aup->stats.rx_dropped++; + aup->netdev->stats.rx_dropped++; continue; } skb_reserve(skb, 1); diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 687c2d53d4d2..6f3e7f71658d 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1194,13 +1194,13 @@ toshoboe_interrupt (int irq, void *dev_id) txp = txpc; txpc++; txpc %= TX_SLOTS; - self->stats.tx_packets++; + self->netdev->stats.tx_packets++; if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS) self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX; } - self->stats.tx_packets--; + self->netdev->stats.tx_packets--; #else - self->stats.tx_packets++; + self->netdev->stats.tx_packets++; #endif toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); } @@ -1280,7 +1280,7 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<'); skb_put (skb, len); skb_copy_to_linear_data(skb, self->rx_bufs[self->rxs], len); - self->stats.rx_packets++; + self->netdev->stats.rx_packets++; skb->dev = self->netdev; skb_reset_mac_header(skb); skb->protocol = htons (ETH_P_IRDA); -- cgit v1.2.3 From 58854c6b411e9e9f46b39bd7092022f639c41904 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 9 Jan 2009 23:19:26 -0800 Subject: r6040: fix ifconfig down and freeing of tx/rx descriptors This patch fixes warnings and such traces that appear when doing an ifconfig down on the interface: WARNING: at arch/x86/kernel/pci-dma.c:376 dma_free_coherent+0x40/0x7d() Modules linked in: Signed-off-by: Joe Chou Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index cf3a082bc89d..b59837e80750 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -457,22 +457,12 @@ static void r6040_down(struct net_device *dev) iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); - free_irq(dev->irq, dev); - - /* Free RX buffer */ - r6040_free_rxbufs(dev); - - /* Free TX buffer */ - r6040_free_txbufs(dev); - - /* Free Descriptor memory */ - pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); - pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); } static int r6040_close(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); + struct pci_dev *pdev = lp->pdev; /* deleted timer */ del_timer_sync(&lp->timer); @@ -481,8 +471,28 @@ static int r6040_close(struct net_device *dev) napi_disable(&lp->napi); netif_stop_queue(dev); r6040_down(dev); + + free_irq(dev->irq, dev); + + /* Free RX buffer */ + r6040_free_rxbufs(dev); + + /* Free TX buffer */ + r6040_free_txbufs(dev); + spin_unlock_irq(&lp->lock); + /* Free Descriptor memory */ + if (lp->rx_ring) { + pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); + lp->rx_ring = 0; + } + + if (lp->tx_ring) { + pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); + lp->tx_ring = 0; + } + return 0; } -- cgit v1.2.3 From 9f1136182f732f6e847fc43bd88b579739d5c211 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 8 Jan 2009 15:04:45 +0000 Subject: r6040: generate random ethernet MAC address when not initialized This patch makes the ethernet driver assign a random ethernet MAC address when the bootloader does not set it. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index b59837e80750..8b5d50927ebf 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -1153,8 +1153,10 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, /* Some bootloader/BIOSes do not initialize * MAC address, warn about that */ - if (!(adrp[0] || adrp[1] || adrp[2])) - printk(KERN_WARNING DRV_NAME ": MAC address not initialized\n"); + if (!(adrp[0] || adrp[1] || adrp[2])) { + printk(KERN_WARNING DRV_NAME ": MAC address not initialized, generating random\n"); + random_ether_addr(dev->dev_addr); + } /* Link new device into r6040_root_dev */ lp->pdev = pdev; -- cgit v1.2.3 From 68334115eecc2502426657a1449dd04b3572ae0d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 8 Jan 2009 15:04:50 +0000 Subject: r6040: no longer mark r6040 as being experimental We do not depend on EXPERIMENTAL and the driver is not experimental, so remove this warning. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 65afda4a62d9..9fe8cb7d43ac 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1600,7 +1600,7 @@ config 8139_OLD_RX_RESET old RX-reset behavior. If unsure, say N. config R6040 - tristate "RDC R6040 Fast Ethernet Adapter support (EXPERIMENTAL)" + tristate "RDC R6040 Fast Ethernet Adapter support" depends on NET_PCI && PCI select CRC32 select MII -- cgit v1.2.3 From e56e356b21c285663712dc39aa9e4303072cbaba Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 8 Jan 2009 15:04:57 +0000 Subject: r6040: bump release to 0.21 Bump version to 0.21 and release date to 09Jan2009. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 8b5d50927ebf..454e7dea0bc2 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include #define DRV_NAME "r6040" -#define DRV_VERSION "0.20" -#define DRV_RELDATE "07Jan2009" +#define DRV_VERSION "0.21" +#define DRV_RELDATE "09Jan2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ -- cgit v1.2.3 From eefacf3b4f8a688aeaddd2f7c46ac5ffceb92472 Mon Sep 17 00:00:00 2001 From: David Graham Date: Thu, 8 Jan 2009 16:03:29 +0000 Subject: e1000e: Add process name to WARN message when detecting Mutex contention Adds process name of the current mutex holder to the WARN message output when the e1000e driver attempts to acquire the nvm_mutex and finds that it is already being held. With this patch the WARN message indicates both the process name of the current mutex holder and the process name of the attempted acquisition, which together will help to identify the contending codepaths. Signed-off-by: David Graham Acked-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index f2a5963b5a95..e415e81ecd3e 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -390,7 +390,8 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) } static DEFINE_MUTEX(nvm_mutex); -static pid_t nvm_owner = -1; +static pid_t nvm_owner_pid = -1; +static char nvm_owner_name[TASK_COMM_LEN] = ""; /** * e1000_acquire_swflag_ich8lan - Acquire software control flag @@ -408,11 +409,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) might_sleep(); if (!mutex_trylock(&nvm_mutex)) { - WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n", - nvm_owner); + WARN(1, KERN_ERR "e1000e mutex contention. Owned by process " + "%s (pid %d), required by process %s (pid %d)\n", + nvm_owner_name, nvm_owner_pid, + current->comm, current->pid); + mutex_lock(&nvm_mutex); } - nvm_owner = current->pid; + nvm_owner_pid = current->pid; + strncpy(nvm_owner_name, current->comm, TASK_COMM_LEN); while (timeout) { extcnf_ctrl = er32(EXTCNF_CTRL); @@ -430,7 +435,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); - nvm_owner = -1; + nvm_owner_pid = -1; + strcpy(nvm_owner_name, ""); mutex_unlock(&nvm_mutex); return -E1000_ERR_CONFIG; } @@ -454,7 +460,8 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); - nvm_owner = -1; + nvm_owner_pid = -1; + strcpy(nvm_owner_name, ""); mutex_unlock(&nvm_mutex); } -- cgit v1.2.3 From 4ca857958c129781b46870ec1d2d13c50aafb8c5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 9 Jan 2009 02:39:57 +0000 Subject: b44: fix misalignment and wasted space in rx handling Broadcom 4400 puts a header of configurable size (apparently needs to be at least 28 bytes) in front of received packets. When handling this, the previous code accidentally added the offset 30 *twice* for the software and once for the hardware, thereby cancelling out the IP alignment effect of the 30 byte padding and wasting an additional 30 bytes of memory per packet. This patch fixes this problem and improves routing throughput by about 30% on MIPS, where unaligned access is expensive. Signed-off-by: Felix Fietkau Signed-off-by: David S. Miller --- drivers/net/b44.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 6926ebedfdc9..5ae131c147f9 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -73,8 +73,8 @@ (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP)) #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) -#define RX_PKT_OFFSET 30 -#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64) +#define RX_PKT_OFFSET (RX_HEADER_LEN + 2) +#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET) /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) @@ -682,7 +682,6 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) } rh = (struct rx_header *) skb->data; - skb_reserve(skb, RX_PKT_OFFSET); rh->len = 0; rh->flags = 0; @@ -693,13 +692,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (src_map != NULL) src_map->skb = NULL; - ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET)); + ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ); if (dest_idx == (B44_RX_RING_SIZE - 1)) ctrl |= DESC_CTRL_EOT; dp = &bp->rx_ring[dest_idx]; dp->ctrl = cpu_to_le32(ctrl); - dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset); + dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset); if (bp->flags & B44_FLAG_RX_RING_HACK) b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma, @@ -809,8 +808,8 @@ static int b44_rx(struct b44 *bp, int budget) ssb_dma_unmap_single(bp->sdev, map, skb_size, DMA_FROM_DEVICE); /* Leave out rx_header */ - skb_put(skb, len + RX_PKT_OFFSET); - skb_pull(skb, RX_PKT_OFFSET); + skb_put(skb, len + RX_PKT_OFFSET); + skb_pull(skb, RX_PKT_OFFSET); } else { struct sk_buff *copy_skb; -- cgit v1.2.3 From c224969e636ea027e7ce474b48e84922e62ca1d6 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 9 Jan 2009 03:14:47 +0000 Subject: qlge: Naming interrupt vectors Name interrupt vectors according to the new naming standard, by Robert Olsson and DaveM. The qlge driver were very close to the new standard, thus the change is kind of trivial. Signed-off-by: Jesper Dangaard Brouer Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index f4c016012f18..b7e40add9586 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2746,14 +2746,14 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev) * Outbound queue is for outbound completions only. */ intr_context->handler = qlge_msix_tx_isr; - sprintf(intr_context->name, "%s-txq-%d", + sprintf(intr_context->name, "%s-tx-%d", qdev->ndev->name, i); } else { /* * Inbound queues handle unicast frames only. */ intr_context->handler = qlge_msix_rx_isr; - sprintf(intr_context->name, "%s-rxq-%d", + sprintf(intr_context->name, "%s-rx-%d", qdev->ndev->name, i); } } -- cgit v1.2.3 From c17931c52ec6b1af710185986e10c344039edeb7 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 9 Jan 2009 03:53:17 +0000 Subject: 3c59x: Use device_set_wakeup_enable Since dev->power.should_wakeup bit is used by the PCI core to decide whether the device should wake up the system from sleep states, set this bit by calling device_set_wakeup_enable(). This restores proper WOL for the 3c59x driver. Reported-and-tested-by: Graeme Wilford Reported-by: Gunnar Degnbol Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 665e7fdf27a1..cdbbb6226fc5 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -3109,6 +3109,8 @@ static void acpi_set_WOL(struct net_device *dev) struct vortex_private *vp = netdev_priv(dev); void __iomem *ioaddr = vp->ioaddr; + device_set_wakeup_enable(vp->gendev, vp->enable_wol); + if (vp->enable_wol) { /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ EL3WINDOW(7); -- cgit v1.2.3 From 0397a2648434a65d73564216c4f96945c192ad4a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 9 Jan 2009 10:23:09 +0000 Subject: drivers/net/hamradio/6pack.c: move a dereference below a NULL test In each case, if the NULL test is necessary, then the dereference should be moved below the NULL test. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ type T; expression E; identifier i,fld; statement S; @@ - T i = E->fld; + T i; ... when != E when != i if (E == NULL) S + i = E->fld; // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 50f1e172ee8f..2d4089894ec7 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -717,11 +717,12 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct sixpack *sp = sp_get(tty); - struct net_device *dev = sp->dev; + struct net_device *dev; unsigned int tmp, err; if (!sp) return -ENXIO; + dev = sp->dev; switch(cmd) { case SIOCGIFNAME: -- cgit v1.2.3 From 43baa5bb26298e8e268056c58900098ce8454548 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 9 Jan 2009 10:23:10 +0000 Subject: drivers/net/wireless/libertas: move a dereference below a NULL test In each case, if the NULL test is necessary, then the dereference should be moved below the NULL test. I have also taken advantage of the availability of the value of priv->dev in the subsequent calls to netif_stop_queue and netif_carrier_off. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ type T; expression E; identifier i,fld; statement S; @@ - T i = E->fld; + T i; ... when != E when != i if (E == NULL) S + i = E->fld; // Signed-off-by: Julia Lawall Acked-by: Dan Williams Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/wireless/libertas/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 3dba83679444..4e0007d20030 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1369,7 +1369,7 @@ EXPORT_SYMBOL_GPL(lbs_start_card); void lbs_stop_card(struct lbs_private *priv) { - struct net_device *dev = priv->dev; + struct net_device *dev; struct cmd_ctrl_node *cmdnode; unsigned long flags; @@ -1377,9 +1377,10 @@ void lbs_stop_card(struct lbs_private *priv) if (!priv) goto out; + dev = priv->dev; - netif_stop_queue(priv->dev); - netif_carrier_off(priv->dev); + netif_stop_queue(dev); + netif_carrier_off(dev); lbs_debugfs_remove_one(priv); if (priv->mesh_tlv) { -- cgit v1.2.3 From 0faac9f75fa4260d67fed5a67bb2f16dbe2e93c8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Jan 2009 10:23:11 +0000 Subject: netdev: gianfar: add MII ioctl handler This is the same kind of wrapper that can also be found in many other network device drivers. Tested with a freescale MPC8349E host CPU: Toggled the interface LEDs on a DP83865 PHY. Signed-off-by: Clifford Wolf Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1b8deca8b9f8..efcbeb6c8673 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -296,6 +296,20 @@ err_out: return err; } +/* Ioctl MII Interface */ +static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct gfar_private *priv = netdev_priv(dev); + + if (!netif_running(dev)) + return -EINVAL; + + if (!priv->phydev) + return -ENODEV; + + return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd); +} + /* Set up the ethernet device structure, private data, * and anything else we need before we start */ static int gfar_probe(struct of_device *ofdev, @@ -366,6 +380,7 @@ static int gfar_probe(struct of_device *ofdev, dev->set_multicast_list = gfar_set_multi; dev->ethtool_ops = &gfar_ethtool_ops; + dev->do_ioctl = gfar_ioctl; if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { priv->rx_csum_enable = 1; -- cgit v1.2.3 From fe96aaa14f553f0eb7af0e3502563a5400c65257 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 11:13:14 +0000 Subject: netdev: add missing set_mac_address hook Many drivers lost the ability to set ethernet address accidently during the net_device_ops conversion. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/3c503.c | 1 + drivers/net/8139cp.c | 2 ++ drivers/net/8139too.c | 2 +- drivers/net/8390.c | 1 + drivers/net/8390p.c | 1 + drivers/net/arm/etherh.c | 1 + drivers/net/e2100.c | 1 + drivers/net/enic/enic_main.c | 1 + drivers/net/hamachi.c | 1 + drivers/net/hp-plus.c | 1 + drivers/net/hydra.c | 1 + drivers/net/mac8390.c | 1 + drivers/net/ne-h8300.c | 1 + drivers/net/ne2k-pci.c | 1 + drivers/net/ns83820.c | 1 + drivers/net/r6040.c | 1 + drivers/net/sc92031.c | 1 + drivers/net/sis900.c | 1 + drivers/net/smc-mca.c | 1 + drivers/net/smc-ultra.c | 1 + drivers/net/smsc911x.c | 1 + drivers/net/smsc9420.c | 1 + drivers/net/via-rhine.c | 1 + drivers/net/via-velocity.c | 1 + drivers/net/wd.c | 1 + drivers/net/yellowfin.c | 1 + drivers/net/zorro8390.c | 1 + 27 files changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index c092c3929224..5b91a85fe107 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -177,6 +177,7 @@ static const struct net_device_ops el2_netdev_ops = { .ndo_get_stats = eip_get_stats, .ndo_set_multicast_list = eip_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = eip_poll, diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index dd7ac8290aec..4e19ae3ce6be 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1821,6 +1821,7 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_open = cp_open, .ndo_stop = cp_close, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_set_multicast_list = cp_set_rx_mode, .ndo_get_stats = cp_get_stats, .ndo_do_ioctl = cp_ioctl, @@ -1832,6 +1833,7 @@ static const struct net_device_ops cp_netdev_ops = { #ifdef BROKEN .ndo_change_mtu = cp_change_mtu, #endif + #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cp_poll_controller, #endif diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index fe370f805793..a5b24202d564 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -917,6 +917,7 @@ static const struct net_device_ops rtl8139_netdev_ops = { .ndo_stop = rtl8139_close, .ndo_get_stats = rtl8139_get_stats, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_start_xmit = rtl8139_start_xmit, .ndo_set_multicast_list = rtl8139_set_rx_mode, .ndo_do_ioctl = netdev_ioctl, @@ -924,7 +925,6 @@ static const struct net_device_ops rtl8139_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = rtl8139_poll_controller, #endif - }; static int __devinit rtl8139_init_one (struct pci_dev *pdev, diff --git a/drivers/net/8390.c b/drivers/net/8390.c index fbe609a51e02..ec3e22e6306f 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -63,6 +63,7 @@ const struct net_device_ops ei_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c index ee70b358a816..da863c91d1d0 100644 --- a/drivers/net/8390p.c +++ b/drivers/net/8390p.c @@ -68,6 +68,7 @@ const struct net_device_ops eip_netdev_ops = { .ndo_get_stats = eip_get_stats, .ndo_set_multicast_list = eip_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = eip_poll, diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 6278606d1049..745ac188babe 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,6 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_addr = eth_set_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index 20eb05cddb83..b07ba1924de0 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -169,6 +169,7 @@ static const struct net_device_ops e21_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index d039e16f2763..7d60551d538f 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1599,6 +1599,7 @@ static const struct net_device_ops enic_netdev_ops = { .ndo_start_xmit = enic_hard_start_xmit, .ndo_get_stats = enic_get_stats, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_set_multicast_list = enic_set_multicast_list, .ndo_change_mtu = enic_change_mtu, .ndo_vlan_rx_register = enic_vlan_rx_register, diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 32200227c923..7e8b3c59a7d6 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -576,6 +576,7 @@ static const struct net_device_ops hamachi_netdev_ops = { .ndo_set_multicast_list = set_rx_mode, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = hamachi_tx_timeout, .ndo_do_ioctl = netdev_ioctl, }; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index b507dbc16e62..5e070f446635 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -166,6 +166,7 @@ static const struct net_device_ops hpp_netdev_ops = { .ndo_get_stats = eip_get_stats, .ndo_set_multicast_list = eip_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = eip_poll, diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 9cb38a8d4387..8ac0930c183c 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -103,6 +103,7 @@ static const struct net_device_ops hydra_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 57716e22660c..8e884869a05b 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -486,6 +486,7 @@ static const struct net_device_ops mac8390_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index b57239171046..7bd6662d5b04 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -202,6 +202,7 @@ static const struct net_device_ops ne_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 62f20ba211cb..f090d3b9ec94 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -208,6 +208,7 @@ static const struct net_device_ops ne2k_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 42021aca1ddd..e80294d8cc19 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1956,6 +1956,7 @@ static const struct net_device_ops netdev_ops = { .ndo_change_mtu = ns83820_change_mtu, .ndo_set_multicast_list = ns83820_set_multicast, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = ns83820_tx_timeout, #ifdef NS83820_VLAN_ACCEL_SUPPORT .ndo_vlan_rx_register = ns83820_vlan_rx_register, diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 454e7dea0bc2..72fd9e97c190 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -1059,6 +1059,7 @@ static const struct net_device_ops r6040_netdev_ops = { .ndo_set_multicast_list = r6040_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = r6040_ioctl, .ndo_tx_timeout = r6040_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 42fd31276602..8b75bef4a841 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1408,6 +1408,7 @@ static const struct net_device_ops sc92031_netdev_ops = { .ndo_set_multicast_list = sc92031_set_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_tx_timeout = sc92031_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = sc92031_poll_controller, diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 4acd41a093ad..6cbefcae9ac2 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -389,6 +389,7 @@ static const struct net_device_ops sis900_netdev_ops = { .ndo_set_multicast_list = set_rx_mode, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = mii_ioctl, .ndo_tx_timeout = sis900_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 404b80e5ba11..8d36d40649ef 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -192,6 +192,7 @@ static const struct net_device_ops ultramca_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index b3866089a206..2033fee3143a 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -196,6 +196,7 @@ static const struct net_device_ops ultra_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index dc3f1108884d..020c5830c37d 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1740,6 +1740,7 @@ static const struct net_device_ops smsc911x_netdev_ops = { .ndo_set_multicast_list = smsc911x_set_multicast_list, .ndo_do_ioctl = smsc911x_do_ioctl, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = smsc911x_poll_controller, #endif diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 27e017d96966..c14a4c6452c7 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1551,6 +1551,7 @@ static const struct net_device_ops smsc9420_netdev_ops = { .ndo_set_multicast_list = smsc9420_set_multicast_list, .ndo_do_ioctl = smsc9420_do_ioctl, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = smsc9420_poll_controller, #endif /* CONFIG_NET_POLL_CONTROLLER */ diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index ac07cc6e3cb2..3b8e63254277 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -622,6 +622,7 @@ static const struct net_device_ops rhine_netdev_ops = { .ndo_get_stats = rhine_get_stats, .ndo_set_multicast_list = rhine_set_rx_mode, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = netdev_ioctl, .ndo_tx_timeout = rhine_tx_timeout, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 58e25d090ae0..a75f91dc3153 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -855,6 +855,7 @@ static const struct net_device_ops velocity_netdev_ops = { .ndo_start_xmit = velocity_xmit, .ndo_get_stats = velocity_get_stats, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_set_multicast_list = velocity_set_multi, .ndo_change_mtu = velocity_change_mtu, .ndo_do_ioctl = velocity_ioctl, diff --git a/drivers/net/wd.c b/drivers/net/wd.c index 3c1edda08d3d..d8322d2d1e29 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -155,6 +155,7 @@ static const struct net_device_ops wd_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index cf9712922778..2f1645dcb8c8 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -362,6 +362,7 @@ static const struct net_device_ops netdev_ops = { .ndo_set_multicast_list = set_rx_mode, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_do_ioctl = netdev_ioctl, .ndo_tx_timeout = yellowfin_tx_timeout, }; diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index affd904deafc..37c84e3b8be0 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -147,6 +147,7 @@ static const struct net_device_ops zorro8390_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, -- cgit v1.2.3 From 52255bbe3551e481b7af423406ca229a13990b1c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 9 Jan 2009 10:45:37 +0000 Subject: netdev: missing validate_address hooks Some devices were converted incorrectly and are missing the validate address hooks. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/acenic.c | 1 + drivers/net/arm/ks8695net.c | 1 + drivers/net/mlx4/en_netdev.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 5b396ff6c83f..9589d620639d 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -460,6 +460,7 @@ static const struct net_device_ops ace_netdev_ops = { .ndo_get_stats = ace_get_stats, .ndo_start_xmit = ace_start_xmit, .ndo_set_multicast_list = ace_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ace_set_mac_addr, .ndo_change_mtu = ace_change_mtu, #if ACENIC_DO_VLAN diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 9ad22d1b00fd..1cf2f949c0b4 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1357,6 +1357,7 @@ static const struct net_device_ops ks8695_netdev_ops = { .ndo_start_xmit = ks8695_start_xmit, .ndo_tx_timeout = ks8695_timeout, .ndo_set_mac_address = ks8695_set_mac, + .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = ks8695_set_multicast, }; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 15bb38d99304..9f6644a44030 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -952,6 +952,7 @@ static const struct net_device_ops mlx4_netdev_ops = { .ndo_get_stats = mlx4_en_get_stats, .ndo_set_multicast_list = mlx4_en_set_multicast, .ndo_set_mac_address = mlx4_en_set_mac, + .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = mlx4_en_change_mtu, .ndo_tx_timeout = mlx4_en_tx_timeout, .ndo_vlan_rx_register = mlx4_en_vlan_rx_register, -- cgit v1.2.3 From 001eb84bbf7205f8cc541a75364a6a0892b5d0a2 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 9 Jan 2009 11:03:44 +0000 Subject: forcedeth: xmit lock fix This patch fixes a potential race condition between xmit thread and xmit completion thread. The calculation of empty tx descriptors is not performed under the lock. This could cause it to set the stop flag while the completion thread finishes all tx's. This will result in the tx queue in stopped state and no one to wake it up. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 5b68dc20168d..6905ec9467df 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2096,14 +2096,15 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); } + spin_lock_irqsave(&np->lock, flags); empty_slots = nv_get_empty_tx_slots(np); if (unlikely(empty_slots <= entries)) { - spin_lock_irqsave(&np->lock, flags); netif_stop_queue(dev); np->tx_stop = 1; spin_unlock_irqrestore(&np->lock, flags); return NETDEV_TX_BUSY; } + spin_unlock_irqrestore(&np->lock, flags); start_tx = put_tx = np->put_tx.orig; @@ -2214,14 +2215,15 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); } + spin_lock_irqsave(&np->lock, flags); empty_slots = nv_get_empty_tx_slots(np); if (unlikely(empty_slots <= entries)) { - spin_lock_irqsave(&np->lock, flags); netif_stop_queue(dev); np->tx_stop = 1; spin_unlock_irqrestore(&np->lock, flags); return NETDEV_TX_BUSY; } + spin_unlock_irqrestore(&np->lock, flags); start_tx = put_tx = np->put_tx.ex; start_tx_ctx = np->put_tx_ctx; -- cgit v1.2.3 From f1405d32e392f2f5f80f4687fe186305de300bf6 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 9 Jan 2009 11:03:54 +0000 Subject: forcedeth: version bump and copyright This patch bumps up the version number and adds current year to copyright. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 6905ec9467df..37a6e956f0b3 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -13,7 +13,7 @@ * Copyright (C) 2004 Andrew de Quincey (wol support) * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane * IRQ rate fixes, bigendian fixes, cleanups, verification) - * Copyright (c) 2004,2005,2006,2007,2008 NVIDIA Corporation + * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.61" +#define FORCEDETH_VERSION "0.62" #define DRV_NAME "forcedeth" #include -- cgit v1.2.3 From ba7cd3ba97f81564be3e4a4ee8ee17726aa853d7 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 9 Jan 2009 11:31:49 +0000 Subject: qlge: Get rid of volatile usage for shadow register. Putting back ql_read_sh_reg() function and using rmb() instead of volatile. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 22 ++++++++++++++++++++-- drivers/net/qlge/qlge_dbg.c | 14 ++++++++------ drivers/net/qlge/qlge_main.c | 12 ++++++------ 3 files changed, 34 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 459663a4023d..4cb3647bb1b0 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1145,7 +1145,7 @@ struct tx_ring { struct wqicb wqicb; /* structure used to inform chip of new queue */ void *wq_base; /* pci_alloc:virtual addr for tx */ dma_addr_t wq_base_dma; /* pci_alloc:dma addr for tx */ - u32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */ + __le32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */ dma_addr_t cnsmr_idx_sh_reg_dma; /* dma-shadow copy of consumer */ u32 wq_size; /* size in bytes of queue area */ u32 wq_len; /* number of entries in queue */ @@ -1181,7 +1181,7 @@ struct rx_ring { u32 cq_size; u32 cq_len; u16 cq_id; - volatile __le32 *prod_idx_sh_reg; /* Shadowed producer register. */ + __le32 *prod_idx_sh_reg; /* Shadowed producer register. */ dma_addr_t prod_idx_sh_reg_dma; void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ u32 cnsmr_idx; /* current sw idx */ @@ -1459,6 +1459,24 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr) mmiowb(); } +/* + * Shadow Registers: + * Outbound queues have a consumer index that is maintained by the chip. + * Inbound queues have a producer index that is maintained by the chip. + * For lower overhead, these registers are "shadowed" to host memory + * which allows the device driver to track the queue progress without + * PCI reads. When an entry is placed on an inbound queue, the chip will + * update the relevant index register and then copy the value to the + * shadow register in host memory. + */ +static inline u32 ql_read_sh_reg(__le32 *addr) +{ + u32 reg; + reg = le32_to_cpu(*addr); + rmb(); + return reg; +} + extern char qlge_driver_name[]; extern const char qlge_driver_version[]; extern const struct ethtool_ops qlge_ethtool_ops; diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 3f5e02d2e4a9..e705ea5b975a 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -455,10 +455,11 @@ void ql_dump_tx_ring(struct tx_ring *tx_ring) printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base); printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n", (unsigned long long) tx_ring->wq_base_dma); - printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n", - tx_ring->cnsmr_idx_sh_reg); - printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n", - (unsigned long long) tx_ring->cnsmr_idx_sh_reg_dma); + printk(KERN_ERR PFX + "tx_ring->cnsmr_idx_sh_reg, addr = 0x%p, value = %d.\n", + tx_ring->cnsmr_idx_sh_reg, + tx_ring->cnsmr_idx_sh_reg + ? ql_read_sh_reg(tx_ring->cnsmr_idx_sh_reg) : 0); printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size); printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len); printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n", @@ -558,9 +559,10 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring) printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size); printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len); printk(KERN_ERR PFX - "rx_ring->prod_idx_sh_reg, addr = %p, value = %d.\n", + "rx_ring->prod_idx_sh_reg, addr = 0x%p, value = %d.\n", rx_ring->prod_idx_sh_reg, - rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0); + rx_ring->prod_idx_sh_reg + ? ql_read_sh_reg(rx_ring->prod_idx_sh_reg) : 0); printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n", (unsigned long long) rx_ring->prod_idx_sh_reg_dma); printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n", diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index b7e40add9586..78df7d11cef1 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1545,7 +1545,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev, static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) { struct ql_adapter *qdev = rx_ring->qdev; - u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); + u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); struct ob_mac_iocb_rsp *net_rsp = NULL; int count = 0; @@ -1571,7 +1571,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) } count++; ql_update_cq(rx_ring); - prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); + prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); } ql_write_cq_idx(rx_ring); if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { @@ -1591,7 +1591,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) { struct ql_adapter *qdev = rx_ring->qdev; - u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); + u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); struct ql_net_rsp_iocb *net_rsp; int count = 0; @@ -1624,7 +1624,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) } count++; ql_update_cq(rx_ring); - prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); + prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); if (count == budget) break; } @@ -1787,7 +1787,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) * Check the default queue and wake handler if active. */ rx_ring = &qdev->rx_ring[0]; - if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { + if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); ql_disable_completion_interrupt(qdev, intr_context->intr); queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, @@ -1801,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) */ for (i = 1; i < qdev->rx_ring_count; i++) { rx_ring = &qdev->rx_ring[i]; - if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != + if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[%d].\n", i); -- cgit v1.2.3 From 97345524392dcbe0157ce2a9d9a589e2022b1c15 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 9 Jan 2009 11:31:50 +0000 Subject: qlge: Get rid of split addresses in hardware control blocks. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 24 ++++++++-------------- drivers/net/qlge/qlge_dbg.c | 48 +++++++++++++++----------------------------- drivers/net/qlge/qlge_main.c | 26 ++++++++---------------- 3 files changed, 32 insertions(+), 66 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 4cb3647bb1b0..969700232265 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -961,8 +961,7 @@ struct ib_mac_iocb_rsp { #define IB_MAC_IOCB_RSP_DS 0x40 /* data is in small buffer */ #define IB_MAC_IOCB_RSP_DL 0x80 /* data is in large buffer */ __le32 data_len; /* */ - __le32 data_addr_lo; /* */ - __le32 data_addr_hi; /* */ + __le64 data_addr; /* */ __le32 rss; /* */ __le16 vlan_id; /* 12 bits */ #define IB_MAC_IOCB_RSP_C 0x1000 /* VLAN CFI bit */ @@ -976,8 +975,7 @@ struct ib_mac_iocb_rsp { #define IB_MAC_IOCB_RSP_HS 0x40 #define IB_MAC_IOCB_RSP_HL 0x80 __le32 hdr_len; /* */ - __le32 hdr_addr_lo; /* */ - __le32 hdr_addr_hi; /* */ + __le64 hdr_addr; /* */ } __attribute((packed)); struct ib_ae_iocb_rsp { @@ -1042,10 +1040,8 @@ struct wqicb { __le16 cq_id_rss; #define Q_CQ_ID_RSS_RV 0x8000 __le16 rid; - __le32 addr_lo; - __le32 addr_hi; - __le32 cnsmr_idx_addr_lo; - __le32 cnsmr_idx_addr_hi; + __le64 addr; + __le64 cnsmr_idx_addr; } __attribute((packed)); /* @@ -1070,18 +1066,14 @@ struct cqicb { #define LEN_CPP_64 0x0002 #define LEN_CPP_128 0x0003 __le16 rid; - __le32 addr_lo; - __le32 addr_hi; - __le32 prod_idx_addr_lo; - __le32 prod_idx_addr_hi; + __le64 addr; + __le64 prod_idx_addr; __le16 pkt_delay; __le16 irq_delay; - __le32 lbq_addr_lo; - __le32 lbq_addr_hi; + __le64 lbq_addr; __le16 lbq_buf_size; __le16 lbq_len; /* entry count */ - __le32 sbq_addr_lo; - __le32 sbq_addr_hi; + __le64 sbq_addr; __le16 sbq_buf_size; __le16 sbq_len; /* entry count */ } __attribute((packed)); diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index e705ea5b975a..379b895ed6e6 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -435,14 +435,10 @@ void ql_dump_wqicb(struct wqicb *wqicb) printk(KERN_ERR PFX "wqicb->cq_id_rss = %d.\n", le16_to_cpu(wqicb->cq_id_rss)); printk(KERN_ERR PFX "wqicb->rid = 0x%x.\n", le16_to_cpu(wqicb->rid)); - printk(KERN_ERR PFX "wqicb->wq_addr_lo = 0x%.08x.\n", - le32_to_cpu(wqicb->addr_lo)); - printk(KERN_ERR PFX "wqicb->wq_addr_hi = 0x%.08x.\n", - le32_to_cpu(wqicb->addr_hi)); - printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_lo = 0x%.08x.\n", - le32_to_cpu(wqicb->cnsmr_idx_addr_lo)); - printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_hi = 0x%.08x.\n", - le32_to_cpu(wqicb->cnsmr_idx_addr_hi)); + printk(KERN_ERR PFX "wqicb->wq_addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(wqicb->addr)); + printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(wqicb->cnsmr_idx_addr)); } void ql_dump_tx_ring(struct tx_ring *tx_ring) @@ -511,30 +507,22 @@ void ql_dump_cqicb(struct cqicb *cqicb) printk(KERN_ERR PFX "cqicb->msix_vect = %d.\n", cqicb->msix_vect); printk(KERN_ERR PFX "cqicb->flags = %x.\n", cqicb->flags); printk(KERN_ERR PFX "cqicb->len = %d.\n", le16_to_cpu(cqicb->len)); - printk(KERN_ERR PFX "cqicb->addr_lo = %x.\n", - le32_to_cpu(cqicb->addr_lo)); - printk(KERN_ERR PFX "cqicb->addr_hi = %x.\n", - le32_to_cpu(cqicb->addr_hi)); - printk(KERN_ERR PFX "cqicb->prod_idx_addr_lo = %x.\n", - le32_to_cpu(cqicb->prod_idx_addr_lo)); - printk(KERN_ERR PFX "cqicb->prod_idx_addr_hi = %x.\n", - le32_to_cpu(cqicb->prod_idx_addr_hi)); + printk(KERN_ERR PFX "cqicb->addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(cqicb->addr)); + printk(KERN_ERR PFX "cqicb->prod_idx_addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(cqicb->prod_idx_addr)); printk(KERN_ERR PFX "cqicb->pkt_delay = 0x%.04x.\n", le16_to_cpu(cqicb->pkt_delay)); printk(KERN_ERR PFX "cqicb->irq_delay = 0x%.04x.\n", le16_to_cpu(cqicb->irq_delay)); - printk(KERN_ERR PFX "cqicb->lbq_addr_lo = %x.\n", - le32_to_cpu(cqicb->lbq_addr_lo)); - printk(KERN_ERR PFX "cqicb->lbq_addr_hi = %x.\n", - le32_to_cpu(cqicb->lbq_addr_hi)); + printk(KERN_ERR PFX "cqicb->lbq_addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(cqicb->lbq_addr)); printk(KERN_ERR PFX "cqicb->lbq_buf_size = 0x%.04x.\n", le16_to_cpu(cqicb->lbq_buf_size)); printk(KERN_ERR PFX "cqicb->lbq_len = 0x%.04x.\n", le16_to_cpu(cqicb->lbq_len)); - printk(KERN_ERR PFX "cqicb->sbq_addr_lo = %x.\n", - le32_to_cpu(cqicb->sbq_addr_lo)); - printk(KERN_ERR PFX "cqicb->sbq_addr_hi = %x.\n", - le32_to_cpu(cqicb->sbq_addr_hi)); + printk(KERN_ERR PFX "cqicb->sbq_addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(cqicb->sbq_addr)); printk(KERN_ERR PFX "cqicb->sbq_buf_size = 0x%.04x.\n", le16_to_cpu(cqicb->sbq_buf_size)); printk(KERN_ERR PFX "cqicb->sbq_len = 0x%.04x.\n", @@ -811,10 +799,8 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp) printk(KERN_ERR PFX "data_len = %d\n", le32_to_cpu(ib_mac_rsp->data_len)); - printk(KERN_ERR PFX "data_addr_hi = 0x%x\n", - le32_to_cpu(ib_mac_rsp->data_addr_hi)); - printk(KERN_ERR PFX "data_addr_lo = 0x%x\n", - le32_to_cpu(ib_mac_rsp->data_addr_lo)); + printk(KERN_ERR PFX "data_addr = 0x%llx\n", + (unsigned long long) le64_to_cpu(ib_mac_rsp->data_addr)); if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK) printk(KERN_ERR PFX "rss = %x\n", le32_to_cpu(ib_mac_rsp->rss)); @@ -830,10 +816,8 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp) if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { printk(KERN_ERR PFX "hdr length = %d.\n", le32_to_cpu(ib_mac_rsp->hdr_len)); - printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n", - le32_to_cpu(ib_mac_rsp->hdr_addr_hi)); - printk(KERN_ERR PFX "hdr addr_lo = 0x%x.\n", - le32_to_cpu(ib_mac_rsp->hdr_addr_lo)); + printk(KERN_ERR PFX "hdr addr = 0x%llx.\n", + (unsigned long long) le64_to_cpu(ib_mac_rsp->hdr_addr)); } } #endif diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 78df7d11cef1..33bbdcefe0a0 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2467,12 +2467,9 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len; cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT); - cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma); - cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32); + cqicb->addr = cpu_to_le64(rx_ring->cq_base_dma); - cqicb->prod_idx_addr_lo = cpu_to_le32(rx_ring->prod_idx_sh_reg_dma); - cqicb->prod_idx_addr_hi = - cpu_to_le32((u64) rx_ring->prod_idx_sh_reg_dma >> 32); + cqicb->prod_idx_addr = cpu_to_le64(rx_ring->prod_idx_sh_reg_dma); /* * Set up the control block load flags. @@ -2483,10 +2480,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) if (rx_ring->lbq_len) { cqicb->flags |= FLAGS_LL; /* Load lbq values */ *((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma; - cqicb->lbq_addr_lo = - cpu_to_le32(rx_ring->lbq_base_indirect_dma); - cqicb->lbq_addr_hi = - cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32); + cqicb->lbq_addr = + cpu_to_le64(rx_ring->lbq_base_indirect_dma); bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 : (u16) rx_ring->lbq_buf_size; cqicb->lbq_buf_size = cpu_to_le16(bq_len); @@ -2501,10 +2496,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) if (rx_ring->sbq_len) { cqicb->flags |= FLAGS_LS; /* Load sbq values */ *((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma; - cqicb->sbq_addr_lo = - cpu_to_le32(rx_ring->sbq_base_indirect_dma); - cqicb->sbq_addr_hi = - cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32); + cqicb->sbq_addr = + cpu_to_le64(rx_ring->sbq_base_indirect_dma); cqicb->sbq_buf_size = cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); bq_len = (rx_ring->sbq_len == 65536) ? 0 : @@ -2611,12 +2604,9 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) Q_FLAGS_LB | Q_FLAGS_LI | Q_FLAGS_LO); wqicb->cq_id_rss = cpu_to_le16(tx_ring->cq_id); wqicb->rid = 0; - wqicb->addr_lo = cpu_to_le32(tx_ring->wq_base_dma); - wqicb->addr_hi = cpu_to_le32((u64) tx_ring->wq_base_dma >> 32); + wqicb->addr = cpu_to_le64(tx_ring->wq_base_dma); - wqicb->cnsmr_idx_addr_lo = cpu_to_le32(tx_ring->cnsmr_idx_sh_reg_dma); - wqicb->cnsmr_idx_addr_hi = - cpu_to_le32((u64) tx_ring->cnsmr_idx_sh_reg_dma >> 32); + wqicb->cnsmr_idx_addr = cpu_to_le64(tx_ring->cnsmr_idx_sh_reg_dma); ql_init_tx_ring(qdev, tx_ring); -- cgit v1.2.3 From 697cdc46801d1106a25d27a8225cb925f0a7f5aa Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 9 Jan 2009 11:31:51 +0000 Subject: qlge: Remove support for device ID 8000. Support for dev id 8000 is pushed out until 2.6.30. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 3 +-- drivers/net/qlge/qlge_main.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 969700232265..a5095343eb11 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -28,8 +28,7 @@ } while (0) #define QLGE_VENDOR_ID 0x1077 -#define QLGE_DEVICE_ID1 0x8012 -#define QLGE_DEVICE_ID 0x8000 +#define QLGE_DEVICE_ID 0x8012 #define MAX_RX_RINGS 128 #define MAX_TX_RINGS 128 diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 33bbdcefe0a0..9931cf7b6ad6 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -76,7 +76,6 @@ MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); static struct pci_device_id qlge_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)}, - {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID1)}, /* required last entry */ {0,} }; -- cgit v1.2.3 From 0857e9d73feea0125280dcd431cee84f6cb3b4e2 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 9 Jan 2009 11:31:52 +0000 Subject: qlge: Fix schedule while atomic issue. There is no need to sleep while waiting for the hardware semaphore to become available. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 9931cf7b6ad6..543a4135ae04 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -126,12 +126,12 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask) int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask) { - unsigned int seconds = 3; + unsigned int wait_count = 30; do { if (!ql_sem_trylock(qdev, sem_mask)) return 0; - ssleep(1); - } while (--seconds); + udelay(100); + } while (--wait_count); return -ETIMEDOUT; } -- cgit v1.2.3 From 683d46a9798c382220ef282b37f8210b5276cb3a Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 9 Jan 2009 11:31:53 +0000 Subject: qlge: Remove dynamic alloc of rx ring control blocks. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 12 ++++++++---- drivers/net/qlge/qlge_main.c | 31 ++----------------------------- 2 files changed, 10 insertions(+), 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index a5095343eb11..c1dadadfab18 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -30,8 +30,9 @@ #define QLGE_VENDOR_ID 0x1077 #define QLGE_DEVICE_ID 0x8012 -#define MAX_RX_RINGS 128 -#define MAX_TX_RINGS 128 +#define MAX_CPUS 8 +#define MAX_TX_RINGS MAX_CPUS +#define MAX_RX_RINGS ((MAX_CPUS * 2) + 1) #define NUM_TX_RING_ENTRIES 256 #define NUM_RX_RING_ENTRIES 256 @@ -44,6 +45,7 @@ #define MAX_SPLIT_SIZE 1023 #define QLGE_SB_PAD 32 +#define MAX_CQ 128 #define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */ #define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */ #define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2) @@ -1393,9 +1395,11 @@ struct ql_adapter { int rx_ring_count; int ring_mem_size; void *ring_mem; - struct rx_ring *rx_ring; + + struct rx_ring rx_ring[MAX_RX_RINGS]; + struct tx_ring tx_ring[MAX_TX_RINGS]; + int rx_csum; - struct tx_ring *tx_ring; u32 default_rx_queue; u16 rx_coalesce_usecs; /* cqicb->int_delay */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 543a4135ae04..45421c8b6010 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2355,28 +2355,6 @@ static void ql_tx_ring_clean(struct ql_adapter *qdev) } } -static void ql_free_ring_cb(struct ql_adapter *qdev) -{ - kfree(qdev->ring_mem); -} - -static int ql_alloc_ring_cb(struct ql_adapter *qdev) -{ - /* Allocate space for tx/rx ring control blocks. */ - qdev->ring_mem_size = - (qdev->tx_ring_count * sizeof(struct tx_ring)) + - (qdev->rx_ring_count * sizeof(struct rx_ring)); - qdev->ring_mem = kmalloc(qdev->ring_mem_size, GFP_KERNEL); - if (qdev->ring_mem == NULL) { - return -ENOMEM; - } else { - qdev->rx_ring = qdev->ring_mem; - qdev->tx_ring = qdev->ring_mem + - (qdev->rx_ring_count * sizeof(struct rx_ring)); - } - return 0; -} - static void ql_free_mem_resources(struct ql_adapter *qdev) { int i; @@ -3236,7 +3214,6 @@ static int qlge_close(struct net_device *ndev) msleep(1); ql_adapter_down(qdev); ql_release_adapter_resources(qdev); - ql_free_ring_cb(qdev); return 0; } @@ -3262,8 +3239,8 @@ static int ql_configure_rings(struct ql_adapter *qdev) * This limitation can be removed when requested. */ - if (cpu_cnt > 8) - cpu_cnt = 8; + if (cpu_cnt > MAX_CPUS) + cpu_cnt = MAX_CPUS; /* * rx_ring[0] is always the default queue. @@ -3283,9 +3260,6 @@ static int ql_configure_rings(struct ql_adapter *qdev) */ qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1; - if (ql_alloc_ring_cb(qdev)) - return -ENOMEM; - for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; memset((void *)tx_ring, 0, sizeof(tx_ring)); @@ -3382,7 +3356,6 @@ static int qlge_open(struct net_device *ndev) error_up: ql_release_adapter_resources(qdev); - ql_free_ring_cb(qdev); return err; } -- cgit v1.2.3 From a7ee2f73f3ce90d73736de1cf432339c35a3faf2 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 9 Jan 2009 22:40:06 -0800 Subject: forcedeth: remove mgmt unit for mcp79 chipset This patch removes the feature flag for mgmt unit as it is not used for this chipset. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 37a6e956f0b3..e06782a60bd5 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -6169,19 +6169,19 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), - .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, }, {0,}, }; -- cgit v1.2.3 From eb10a781824ca63c4e484c4642a19b3370980792 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sun, 11 Jan 2009 00:09:04 -0800 Subject: forcedeth: napi schedule lock fix This patch fixes a potential race condition between scheduling napi and completing napi poll. The call to netif_rx_schedule should be under protection of the lock (as is the completion), otherwise, interrupts could be masked off. Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e06782a60bd5..5b910cf63740 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3405,10 +3405,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data) #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { + spin_lock(&np->lock); netif_rx_schedule(&np->napi); /* Disable furthur receive irq's */ - spin_lock(&np->lock); np->irqmask &= ~NVREG_IRQ_RX_ALL; if (np->msi_flags & NV_MSI_X_ENABLED) @@ -3522,10 +3522,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { + spin_lock(&np->lock); netif_rx_schedule(&np->napi); /* Disable furthur receive irq's */ - spin_lock(&np->lock); np->irqmask &= ~NVREG_IRQ_RX_ALL; if (np->msi_flags & NV_MSI_X_ENABLED) -- cgit v1.2.3 From 702403af28ef647b090b49bb61abebb45150ce7f Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Sun, 11 Jan 2009 00:14:27 -0800 Subject: smsc911x: fix smsc911x_reg_read compiler warning if this code path is ever hit, the platform_data struct isn't properly configured with a bus width flag so the device won't work (hence the BUG()). This patch adds a dummy return statement to eliminate this compiler warning: drivers/net/smsc911x.c: In function 'smsc911x_reg_read': drivers/net/smsc911x.c:148: warning: control reaches end of non-void function Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 020c5830c37d..fd3d2a7a1a24 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -144,6 +144,7 @@ static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg) } BUG(); + return 0; } static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg, -- cgit v1.2.3 From 08168f7164fed494852361ab900358cd7a6b95d6 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Sun, 11 Jan 2009 00:14:52 -0800 Subject: smsc911x: register irq with device name, not driver name This change lets "cat /proc/interrupts" show the name of the ethernet device (e.g. eth0) rather than the driver name (smsc911x). Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index fd3d2a7a1a24..f513bdf1c887 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1969,7 +1969,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED, - SMSC_CHIPNAME, dev); + dev->name, dev); if (retval) { SMSC_WARNING(PROBE, "Unable to claim requested irq: %d", dev->irq); -- cgit v1.2.3 From 2a7e637de51ded7b0b56b927f45915eadb6734bb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 11 Jan 2009 00:18:13 -0800 Subject: sfc: SFT9001: Fix condition for LNPGA power-off Only the SFX7101 requires software power control. This was incorrectly being applied to the SFT9001 rev A as well. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/tenxpress.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index b9768760fae7..9ecb77da9545 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -636,10 +636,11 @@ static void tenxpress_phy_fini(struct efx_nic *efx) { int reg; - if (efx->phy_type == PHY_TYPE_SFT9001B) { + if (efx->phy_type == PHY_TYPE_SFT9001B) device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_short_reach); - } else { + + if (efx->phy_type == PHY_TYPE_SFX7101) { /* Power down the LNPGA */ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, -- cgit v1.2.3 From 47fd23fe8efeea3af4593a8424419df48724eb25 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sun, 11 Jan 2009 00:19:36 -0800 Subject: cxgb3: Keep LRO off if disabled when interface is down I have a system with a Chelsio adapter (driven by cxgb3) whose ports are part of a Linux bridge. Recently I updated the kernel and discovered that things stopped working because cxgb3 was doing LRO on packets that were passed into the bridge code for forwarding. (Incidentally, this problem manifested itself in a strange way that made debugging a bit interesting -- for some reason, the skb_warn_if_lro() check in bridge didn't trigger and these LROed packets were forwarded out a forcedeth interface, and caused the forcedeth transmit path to get stuck) This is because cxgb3 has no way of keeping state for the LRO flag until the interface is brought up, so if the bridging code disables LRO while the interface is down, then cxgb3_up() will just reenable LRO, and on my Debian system at least, the init scripts add interfaces to a bridge before bringing the interfaces up. Fix this by keeping track of each interface's LRO state in cxgb3 so that when bridge disables LRO, it stays disabled in cxgb3_up() when the interface is brought up. I did this by changing the rx_csum_offload flag into a pair of bit flags; the effect of this on the rx_eth() fast path is miniscule enough that it should be fine (eg on x86, a cmpb instruction becomes a testb instruction). Signed-off-by: Roland Dreier Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 7 ++++++- drivers/net/cxgb3/cxgb3_main.c | 22 ++++++++++++++-------- drivers/net/cxgb3/sge.c | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 5b346f9eaa8b..a89d8cc51205 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -50,12 +50,17 @@ struct vlan_group; struct adapter; struct sge_qset; +enum { /* rx_offload flags */ + T3_RX_CSUM = 1 << 0, + T3_LRO = 1 << 1, +}; + struct port_info { struct adapter *adapter; struct vlan_group *vlan_grp; struct sge_qset *qs; u8 port_id; - u8 rx_csum_offload; + u8 rx_offload; u8 nqsets; u8 first_qset; struct cphy phy; diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 2847f947499d..0089746b8d02 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -546,7 +546,7 @@ static int setup_sge_qsets(struct adapter *adap) pi->qs = &adap->sge.qs[pi->first_qset]; for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; ++j, ++qset_idx) { - set_qset_lro(dev, qset_idx, pi->rx_csum_offload); + set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); err = t3_sge_alloc_qset(adap, qset_idx, 1, (adap->flags & USING_MSIX) ? qset_idx + 1 : irq_idx, @@ -1657,17 +1657,19 @@ static u32 get_rx_csum(struct net_device *dev) { struct port_info *p = netdev_priv(dev); - return p->rx_csum_offload; + return p->rx_offload & T3_RX_CSUM; } static int set_rx_csum(struct net_device *dev, u32 data) { struct port_info *p = netdev_priv(dev); - p->rx_csum_offload = data; - if (!data) { + if (data) { + p->rx_offload |= T3_RX_CSUM; + } else { int i; + p->rx_offload &= ~(T3_RX_CSUM | T3_LRO); for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) set_qset_lro(dev, i, 0); } @@ -1830,15 +1832,18 @@ static int cxgb3_set_flags(struct net_device *dev, u32 data) int i; if (data & ETH_FLAG_LRO) { - if (!pi->rx_csum_offload) + if (!(pi->rx_offload & T3_RX_CSUM)) return -EINVAL; + pi->rx_offload |= T3_LRO; for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) set_qset_lro(dev, i, 1); - } else + } else { + pi->rx_offload &= ~T3_LRO; for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) set_qset_lro(dev, i, 0); + } return 0; } @@ -1926,7 +1931,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) pi = adap2pinfo(adapter, i); if (t.qset_idx >= pi->first_qset && t.qset_idx < pi->first_qset + pi->nqsets && - !pi->rx_csum_offload) + !(pi->rx_offload & T3_RX_CSUM)) return -EINVAL; } @@ -2946,7 +2951,7 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->port[i] = netdev; pi = netdev_priv(netdev); pi->adapter = adapter; - pi->rx_csum_offload = 1; + pi->rx_offload = T3_RX_CSUM | T3_LRO; pi->port_id = i; netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); @@ -2955,6 +2960,7 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->mem_end = mmio_start + mmio_len - 1; netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; netdev->features |= NETIF_F_LLTX; + netdev->features |= NETIF_F_LRO; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 6c641a889471..14f9fb3e8795 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1932,7 +1932,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, skb_pull(skb, sizeof(*p) + pad); skb->protocol = eth_type_trans(skb, adap->port[p->iff]); pi = netdev_priv(skb->dev); - if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) && + if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && p->csum == htons(0xffff) && !p->fragment) { qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++; skb->ip_summed = CHECKSUM_UNNECESSARY; -- cgit v1.2.3 From 3bc53427e4f323d4f33f70477fc32c1c2ae7fb5d Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Sun, 11 Jan 2009 00:25:21 -0800 Subject: ucc_geth: use correct UCCE macros The UCC Event Register (UCCE) already has unambigous macro definitions in qe.h, so we should not be defining our own in the UCC Ethernet driver. Removed unused local variable 'dev' from ucc_geth_poll(), which fixes a warning caused by commit 908a7a16b852ffd618a9127be8d62432182d81b4 ("net: Remove unused netdev arg from some NAPI interfaces."). Replaced in_be/out_be pairs with setbits32 or clrbits32, where applicable. Signed-off-by: Timur Tabi Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 128 +++++++++++++++++-------------------------------- drivers/net/ucc_geth.h | 114 ++++++++++--------------------------------- 2 files changed, 68 insertions(+), 174 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 7d5a1303e30d..11441225bf41 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -442,40 +442,30 @@ static void magic_packet_detection_enable(struct ucc_geth_private *ugeth) { struct ucc_fast_private *uccf; struct ucc_geth __iomem *ug_regs; - u32 maccfg2, uccm; uccf = ugeth->uccf; ug_regs = ugeth->ug_regs; /* Enable interrupts for magic packet detection */ - uccm = in_be32(uccf->p_uccm); - uccm |= UCCE_MPD; - out_be32(uccf->p_uccm, uccm); + setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD); /* Enable magic packet detection */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 |= MACCFG2_MPE; - out_be32(&ug_regs->maccfg2, maccfg2); + setbits32(&ug_regs->maccfg2, MACCFG2_MPE); } static void magic_packet_detection_disable(struct ucc_geth_private *ugeth) { struct ucc_fast_private *uccf; struct ucc_geth __iomem *ug_regs; - u32 maccfg2, uccm; uccf = ugeth->uccf; ug_regs = ugeth->ug_regs; /* Disable interrupts for magic packet detection */ - uccm = in_be32(uccf->p_uccm); - uccm &= ~UCCE_MPD; - out_be32(uccf->p_uccm, uccm); + clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD); /* Disable magic packet detection */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 &= ~MACCFG2_MPE; - out_be32(&ug_regs->maccfg2, maccfg2); + clrbits32(&ug_regs->maccfg2, MACCFG2_MPE); } #endif /* MAGIC_PACKET */ @@ -585,7 +575,8 @@ static void get_statistics(struct ucc_geth_private *ugeth, /* Hardware only if user handed pointer and driver actually gathers hardware statistics */ - if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) { + if (hardware_statistics && + (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) { hardware_statistics->tx64 = in_be32(&ug_regs->tx64); hardware_statistics->tx127 = in_be32(&ug_regs->tx127); hardware_statistics->tx255 = in_be32(&ug_regs->tx255); @@ -1181,9 +1172,7 @@ int init_flow_control_params(u32 automatic_flow_control_mode, out_be32(uempr_register, value); /* Set UPSMR register */ - value = in_be32(upsmr_register); - value |= automatic_flow_control_mode; - out_be32(upsmr_register, value); + setbits32(upsmr_register, automatic_flow_control_mode); value = in_be32(maccfg1_register); if (rx_flow_control_enable) @@ -1200,14 +1189,11 @@ static int init_hw_statistics_gathering_mode(int enable_hardware_statistics, u32 __iomem *upsmr_register, u16 __iomem *uescr_register) { - u32 upsmr_value = 0; u16 uescr_value = 0; + /* Enable hardware statistics gathering if requested */ - if (enable_hardware_statistics) { - upsmr_value = in_be32(upsmr_register); - upsmr_value |= UPSMR_HSE; - out_be32(upsmr_register, upsmr_value); - } + if (enable_hardware_statistics) + setbits32(upsmr_register, UCC_GETH_UPSMR_HSE); /* Clear hardware statistics counters */ uescr_value = in_be16(uescr_register); @@ -1233,23 +1219,17 @@ static int init_firmware_statistics_gathering_mode(int { /* Note: this function does not check if */ /* the parameters it receives are NULL */ - u16 temoder_value; - u32 remoder_value; if (enable_tx_firmware_statistics) { out_be32(tx_rmon_base_ptr, tx_firmware_statistics_structure_address); - temoder_value = in_be16(temoder_register); - temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE; - out_be16(temoder_register, temoder_value); + setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE); } if (enable_rx_firmware_statistics) { out_be32(rx_rmon_base_ptr, rx_firmware_statistics_structure_address); - remoder_value = in_be32(remoder_register); - remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE; - out_be32(remoder_register, remoder_value); + setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE); } return 0; @@ -1316,15 +1296,12 @@ static int init_check_frame_length_mode(int length_check, static int init_preamble_length(u8 preamble_length, u32 __iomem *maccfg2_register) { - u32 value = 0; - if ((preamble_length < 3) || (preamble_length > 7)) return -EINVAL; - value = in_be32(maccfg2_register); - value &= ~MACCFG2_PREL_MASK; - value |= (preamble_length << MACCFG2_PREL_SHIFT); - out_be32(maccfg2_register, value); + clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK, + preamble_length << MACCFG2_PREL_SHIFT); + return 0; } @@ -1337,19 +1314,19 @@ static int init_rx_parameters(int reject_broadcast, value = in_be32(upsmr_register); if (reject_broadcast) - value |= UPSMR_BRO; + value |= UCC_GETH_UPSMR_BRO; else - value &= ~UPSMR_BRO; + value &= ~UCC_GETH_UPSMR_BRO; if (receive_short_frames) - value |= UPSMR_RSH; + value |= UCC_GETH_UPSMR_RSH; else - value &= ~UPSMR_RSH; + value &= ~UCC_GETH_UPSMR_RSH; if (promiscuous) - value |= UPSMR_PRO; + value |= UCC_GETH_UPSMR_PRO; else - value &= ~UPSMR_PRO; + value &= ~UCC_GETH_UPSMR_PRO; out_be32(upsmr_register, value); @@ -1410,26 +1387,27 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) /* Set UPSMR */ upsmr = in_be32(&uf_regs->upsmr); - upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); + upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M | + UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM); if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - upsmr |= UPSMR_RPM; + upsmr |= UCC_GETH_UPSMR_RPM; switch (ugeth->max_speed) { case SPEED_10: - upsmr |= UPSMR_R10M; + upsmr |= UCC_GETH_UPSMR_R10M; /* FALLTHROUGH */ case SPEED_100: if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) - upsmr |= UPSMR_RMM; + upsmr |= UCC_GETH_UPSMR_RMM; } } if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - upsmr |= UPSMR_TBIM; + upsmr |= UCC_GETH_UPSMR_TBIM; } out_be32(&uf_regs->upsmr, upsmr); @@ -1517,9 +1495,9 @@ static void adjust_link(struct net_device *dev) (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { if (phydev->speed == SPEED_10) - upsmr |= UPSMR_R10M; + upsmr |= UCC_GETH_UPSMR_R10M; else - upsmr &= ~(UPSMR_R10M); + upsmr &= ~UCC_GETH_UPSMR_R10M; } break; default: @@ -1602,10 +1580,8 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) uccf = ugeth->uccf; /* Mask GRACEFUL STOP TX interrupt bit and clear it */ - temp = in_be32(uccf->p_uccm); - temp &= ~UCCE_GRA; - out_be32(uccf->p_uccm, temp); - out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */ + clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA); + out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */ /* Issue host command */ cecr_subblock = @@ -1617,7 +1593,7 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) do { msleep(10); temp = in_be32(uccf->p_ucce); - } while (!(temp & UCCE_GRA) && --i); + } while (!(temp & UCC_GETH_UCCE_GRA) && --i); uccf->stopped_tx = 1; @@ -1975,12 +1951,9 @@ static void ucc_geth_set_multi(struct net_device *dev) uf_regs = ugeth->uccf->uf_regs; if (dev->flags & IFF_PROMISC) { - - out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr) | UPSMR_PRO); - + setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); } else { - - out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr)&~UPSMR_PRO); + clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); p_82xx_addr_filt = (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth-> @@ -2020,7 +1993,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) { struct ucc_geth __iomem *ug_regs = ugeth->ug_regs; struct phy_device *phydev = ugeth->phydev; - u32 tempval; ugeth_vdbg("%s: IN", __func__); @@ -2037,9 +2009,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) out_be32(ugeth->uccf->p_ucce, 0xffffffff); /* Disable Rx and Tx */ - tempval = in_be32(&ug_regs->maccfg1); - tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); - out_be32(&ug_regs->maccfg1, tempval); + clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); ucc_geth_memclean(ugeth); } @@ -2153,10 +2123,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* Generate uccm_mask for receive */ uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */ for (i = 0; i < ug_info->numQueuesRx; i++) - uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i); + uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i); for (i = 0; i < ug_info->numQueuesTx; i++) - uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); + uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i); /* Initialize the general fast UCC block. */ if (ucc_fast_init(uf_info, &ugeth->uccf)) { if (netif_msg_probe(ugeth)) @@ -2185,7 +2155,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) struct ucc_geth __iomem *ug_regs; int ret_val = -EINVAL; u32 remoder = UCC_GETH_REMODER_INIT; - u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; + u32 init_enet_pram_offset, cecr_subblock, command; u32 ifstat, i, j, size, l2qt, l3qt, length; u16 temoder = UCC_GETH_TEMODER_INIT; u16 test; @@ -2281,10 +2251,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) &uf_regs->upsmr, &ug_regs->uempr, &ug_regs->maccfg1); - maccfg1 = in_be32(&ug_regs->maccfg1); - maccfg1 |= MACCFG1_ENABLE_RX; - maccfg1 |= MACCFG1_ENABLE_TX; - out_be32(&ug_regs->maccfg1, maccfg1); + setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); /* Set IPGIFG */ /* For more details see the hardware spec. */ @@ -3274,7 +3241,6 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) static int ucc_geth_poll(struct napi_struct *napi, int budget) { struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi); - struct net_device *dev = ugeth->dev; struct ucc_geth_info *ug_info; int howmany, i; @@ -3285,14 +3251,8 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget) howmany += ucc_geth_rx(ugeth, i, budget - howmany); if (howmany < budget) { - struct ucc_fast_private *uccf; - u32 uccm; - netif_rx_complete(napi); - uccf = ugeth->uccf; - uccm = in_be32(uccf->p_uccm); - uccm |= UCCE_RX_EVENTS; - out_be32(uccf->p_uccm, uccm); + setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS); } return howmany; @@ -3332,7 +3292,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) /* Tx event processing */ if (ucce & UCCE_TX_EVENTS) { spin_lock(&ugeth->lock); - tx_mask = UCCE_TXBF_SINGLE_MASK; + tx_mask = UCC_GETH_UCCE_TXB0; for (i = 0; i < ug_info->numQueuesTx; i++) { if (ucce & tx_mask) ucc_geth_tx(dev, i); @@ -3344,12 +3304,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) /* Errors and other events */ if (ucce & UCCE_OTHER) { - if (ucce & UCCE_BSY) { + if (ucce & UCC_GETH_UCCE_BSY) dev->stats.rx_errors++; - } - if (ucce & UCCE_TXE) { + if (ucce & UCC_GETH_UCCE_TXE) dev->stats.tx_errors++; - } } return IRQ_HANDLED; diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index d74d2f7cb739..8f699cb773ee 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -162,92 +162,27 @@ struct ucc_geth { boundary */ /* UCC GETH Event Register */ -#define UCCE_MPD 0x80000000 /* Magic packet - detection */ -#define UCCE_SCAR 0x40000000 -#define UCCE_GRA 0x20000000 /* Tx graceful - stop - complete */ -#define UCCE_CBPR 0x10000000 -#define UCCE_BSY 0x08000000 -#define UCCE_RXC 0x04000000 -#define UCCE_TXC 0x02000000 -#define UCCE_TXE 0x01000000 -#define UCCE_TXB7 0x00800000 -#define UCCE_TXB6 0x00400000 -#define UCCE_TXB5 0x00200000 -#define UCCE_TXB4 0x00100000 -#define UCCE_TXB3 0x00080000 -#define UCCE_TXB2 0x00040000 -#define UCCE_TXB1 0x00020000 -#define UCCE_TXB0 0x00010000 -#define UCCE_RXB7 0x00008000 -#define UCCE_RXB6 0x00004000 -#define UCCE_RXB5 0x00002000 -#define UCCE_RXB4 0x00001000 -#define UCCE_RXB3 0x00000800 -#define UCCE_RXB2 0x00000400 -#define UCCE_RXB1 0x00000200 -#define UCCE_RXB0 0x00000100 -#define UCCE_RXF7 0x00000080 -#define UCCE_RXF6 0x00000040 -#define UCCE_RXF5 0x00000020 -#define UCCE_RXF4 0x00000010 -#define UCCE_RXF3 0x00000008 -#define UCCE_RXF2 0x00000004 -#define UCCE_RXF1 0x00000002 -#define UCCE_RXF0 0x00000001 - -#define UCCE_RXBF_SINGLE_MASK (UCCE_RXF0) -#define UCCE_TXBF_SINGLE_MASK (UCCE_TXB0) - -#define UCCE_TXB (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\ - UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0) -#define UCCE_RXB (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\ - UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0) -#define UCCE_RXF (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\ - UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0) -#define UCCE_OTHER (UCCE_SCAR | UCCE_GRA | UCCE_CBPR | UCCE_BSY |\ - UCCE_RXC | UCCE_TXC | UCCE_TXE) - -#define UCCE_RX_EVENTS (UCCE_RXF | UCCE_BSY) -#define UCCE_TX_EVENTS (UCCE_TXB | UCCE_TXE) - -/* UCC GETH UPSMR (Protocol Specific Mode Register) */ -#define UPSMR_ECM 0x04000000 /* Enable CAM - Miss or - Enable - Filtering - Miss */ -#define UPSMR_HSE 0x02000000 /* Hardware - Statistics - Enable */ -#define UPSMR_PRO 0x00400000 /* Promiscuous*/ -#define UPSMR_CAP 0x00200000 /* CAM polarity - */ -#define UPSMR_RSH 0x00100000 /* Receive - Short Frames - */ -#define UPSMR_RPM 0x00080000 /* Reduced Pin - Mode - interfaces */ -#define UPSMR_R10M 0x00040000 /* RGMII/RMII - 10 Mode */ -#define UPSMR_RLPB 0x00020000 /* RMII - Loopback - Mode */ -#define UPSMR_TBIM 0x00010000 /* Ten-bit - Interface - Mode */ -#define UPSMR_RMM 0x00001000 /* RMII/RGMII - Mode */ -#define UPSMR_CAM 0x00000400 /* CAM Address - Matching */ -#define UPSMR_BRO 0x00000200 /* Broadcast - Address */ -#define UPSMR_RES1 0x00002000 /* Reserved - feild - must - be 1 */ +#define UCCE_TXB (UCC_GETH_UCCE_TXB7 | UCC_GETH_UCCE_TXB6 | \ + UCC_GETH_UCCE_TXB5 | UCC_GETH_UCCE_TXB4 | \ + UCC_GETH_UCCE_TXB3 | UCC_GETH_UCCE_TXB2 | \ + UCC_GETH_UCCE_TXB1 | UCC_GETH_UCCE_TXB0) + +#define UCCE_RXB (UCC_GETH_UCCE_RXB7 | UCC_GETH_UCCE_RXB6 | \ + UCC_GETH_UCCE_RXB5 | UCC_GETH_UCCE_RXB4 | \ + UCC_GETH_UCCE_RXB3 | UCC_GETH_UCCE_RXB2 | \ + UCC_GETH_UCCE_RXB1 | UCC_GETH_UCCE_RXB0) + +#define UCCE_RXF (UCC_GETH_UCCE_RXF7 | UCC_GETH_UCCE_RXF6 | \ + UCC_GETH_UCCE_RXF5 | UCC_GETH_UCCE_RXF4 | \ + UCC_GETH_UCCE_RXF3 | UCC_GETH_UCCE_RXF2 | \ + UCC_GETH_UCCE_RXF1 | UCC_GETH_UCCE_RXF0) + +#define UCCE_OTHER (UCC_GETH_UCCE_SCAR | UCC_GETH_UCCE_GRA | \ + UCC_GETH_UCCE_CBPR | UCC_GETH_UCCE_BSY | \ + UCC_GETH_UCCE_RXC | UCC_GETH_UCCE_TXC | UCC_GETH_UCCE_TXE) + +#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY) +#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE) /* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ #define MACCFG1_FLOW_RX 0x00000020 /* Flow Control @@ -945,9 +880,10 @@ struct ucc_geth_hardware_statistics { #define UCC_GETH_REMODER_INIT 0 /* bits that must be set */ #define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */ -#define UCC_GETH_UPSMR_INIT (UPSMR_RES1) /* Start value - for this - register */ + +/* Initial value for UPSMR */ +#define UCC_GETH_UPSMR_INIT UCC_GETH_UPSMR_RES1 + #define UCC_GETH_MACCFG1_INIT 0 #define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1) -- cgit v1.2.3 From 8476a6571005f9440adda08ca4d6c69c7f4db30b Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Tue, 30 Dec 2008 22:49:28 +0100 Subject: Wireless: Fix Kconfig fact error Raytheon cards use 2.4 GHz, not 2.4 MHz. See http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Linux.Wireless.drivers.html#Raylink Signed-off-by: Erik Ekman Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index ea543fcf2687..e4f9f747de88 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -111,7 +111,7 @@ config WLAN_80211 lets you choose drivers. config PCMCIA_RAYCS - tristate "Aviator/Raytheon 2.4MHz wireless support" + tristate "Aviator/Raytheon 2.4GHz wireless support" depends on PCMCIA && WLAN_80211 select WIRELESS_EXT ---help--- -- cgit v1.2.3 From d1b29405bd3590bc97c4d3ff2c9139ca55e56ccd Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Fri, 2 Jan 2009 08:05:27 +0000 Subject: rt2x00: Fix radio LED type check Since "rt2x00: Fix LED state handling", rt2x00leds_led_radio wrongly checks that the LED type is LED_TYPE_ASSOC. This patch makes it check for LED_TYPE_RADIO once again. Signed-off-by: Andrew Price Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00leds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 68f4e0fc35b9..a0cd35b6beb5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -97,7 +97,7 @@ void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) { - if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC) + if (rt2x00dev->led_radio.type == LED_TYPE_RADIO) rt2x00led_led_simple(&rt2x00dev->led_radio, enabled); } -- cgit v1.2.3 From 51fb80fefe736db1182551fec6528d1ef095b0ea Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 3 Jan 2009 12:45:12 -0600 Subject: p54usb: Fix to prevent SKB memory allocation errors with 4K page size On x86_64 architecture with 4K page size and SLUB debugging enabled, stress testing on p54usb has resulted in skb allocation failures of O(1) and extreme page fragmentation. Reducing rx_mtu fixes this problem by reducing the size of all receive skb allocations to be of O(0). This change does not impact performance in any way. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 82354b974a04..06c64744df27 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -138,6 +138,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) u8 *fw_version = NULL; size_t len; int i; + int maxlen; if (priv->rx_start) return 0; @@ -195,6 +196,16 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) else priv->rx_mtu = (size_t) 0x620 - priv->tx_hdr_len; + maxlen = priv->tx_hdr_len + /* USB devices */ + sizeof(struct p54_rx_data) + + 4 + /* rx alignment */ + IEEE80211_MAX_FRAG_THRESHOLD; + if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) { + printk(KERN_INFO "p54: rx_mtu reduced from %d " + "to %d\n", priv->rx_mtu, + maxlen); + priv->rx_mtu = maxlen; + } break; } case BR_CODE_EXPOSED_IF: -- cgit v1.2.3 From 3be36ae223271f9c2cfbe7406846c8fdcd2f50c3 Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Sun, 4 Jan 2009 01:10:49 +0100 Subject: rt2x00: add USB ID for the Linksys WUSB200. add USB ID for the Linksys WUSB200 Wireless-G Business USB Adapter to rt73usb. Signed-off-by: Stefan Lippers-Hollmann Cc: stable Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d638a8a59370..96a8d69f8790 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2321,6 +2321,7 @@ static struct usb_device_id rt73usb_device_table[] = { /* Linksys */ { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, -- cgit v1.2.3 From 3ea96463156123cbfd09ac412012a87fef068830 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 4 Jan 2009 17:33:25 +0100 Subject: rt2x00: Fix TX short preamble detection The short preamble mode was not correctly detected during TX, rt2x00 used the rate->hw_value_short field but mac80211 is not using this field that way. Instead the flag IEEE80211_TX_RC_USE_SHORT_PREAMBLE should be used to determine if the frame should be send out using short preamble or not. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 8 +++----- drivers/net/wireless/rt2x00/rt2x00lib.h | 11 ----------- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- 3 files changed, 4 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6d92542fcf0d..87c0f2c83077 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -807,13 +807,11 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, { entry->flags = 0; entry->bitrate = rate->bitrate; - entry->hw_value = rt2x00_create_rate_hw_value(index, 0); - entry->hw_value_short = entry->hw_value; + entry->hw_value =index; + entry->hw_value_short = index; - if (rate->flags & DEV_RATE_SHORT_PREAMBLE) { + if (rate->flags & DEV_RATE_SHORT_PREAMBLE) entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; - entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1); - } } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 03024327767b..86cd26fbf769 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -52,22 +52,11 @@ struct rt2x00_rate { extern const struct rt2x00_rate rt2x00_supported_rates[12]; -static inline u16 rt2x00_create_rate_hw_value(const u16 index, - const u16 short_preamble) -{ - return (short_preamble << 8) | (index & 0xff); -} - static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) { return &rt2x00_supported_rates[hw_value & 0xff]; } -static inline int rt2x00_get_rate_preamble(const u16 hw_value) -{ - return (hw_value & 0xff00); -} - /* * Radio control handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index eaec6bd93ed5..746a8f36b931 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -313,7 +313,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (rt2x00_get_rate_preamble(rate->hw_value)) + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) txdesc->signal |= 0x08; } } -- cgit v1.2.3 From 878e6a432f85690a2c0d88d96f177e54ff1d4a57 Mon Sep 17 00:00:00 2001 From: Michiel Date: Sun, 4 Jan 2009 17:22:28 -0600 Subject: p54usb: Add USB ID for Thomson Speedtouch 121g Add the USB ID for Thomson Speedtouch 121g to p54usb. Signed-off-by: Michiel Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index c44a200059d2..8f5c063b854b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ + {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ -- cgit v1.2.3 From 176ddc7dcfe3fd93778f52abf9a947d92932f19e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 5 Jan 2009 13:51:24 +0200 Subject: ath9k: Enforce module build if rfkill is a module CONFIG_ATH9K=y results in build issues if CONFIG_RFKILL=m since ath9k does not depend on rfkill in kconfig (i.e., CONFIG_RFKILL is used to select whether to enable rfkill in ath9k), but uses its functions if rfkill is enabled. Enforce ath9k to be build as a module if CONFIG_RFKILL=m to avoid this invalid configuration. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig index c43bd321f97f..90a8dd873786 100644 --- a/drivers/net/wireless/ath9k/Kconfig +++ b/drivers/net/wireless/ath9k/Kconfig @@ -1,6 +1,7 @@ config ATH9K tristate "Atheros 802.11n wireless cards support" depends on PCI && MAC80211 && WLAN_80211 + depends on RFKILL || RFKILL=n select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS -- cgit v1.2.3 From 20953ad68ee522f6420b63c200ac9b23f96d937a Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Wed, 7 Jan 2009 00:23:55 +0000 Subject: orinoco: take the driver lock in the rx tasklet Fix the warning reproduced below. We add to rx_list in interrupt context and remove elements in tasklet context. While removing elements we need to prevent the interrupt modifying the list. Note that "orinoco: Process bulk of receive interrupt in a tasklet" did not preserve locking semantics on what is now orinoco_rx. This patch reinstates the locking semantics and ensures it covers rx_list as well. This leads to additional cleanup required in free_orinocodev. [89479.105038] WARNING: at lib/list_debug.c:30 __list_add+0x8f/0xa0() [89479.105058] list_add corruption. prev->next should be next (dddb3568), but was cbc28978. (prev=dddb3568). [89479.106002] Pid: 15746, comm: X Not tainted 2.6.28-1avb #26 [89479.106020] Call Trace: [89479.106062] [] warn_slowpath+0x60/0x80 [89479.106104] [] ? native_sched_clock+0x20/0x70 [89479.106194] [] ? lock_release_holdtime+0x35/0x200 [89479.106218] [] ? __slab_alloc+0x550/0x560 [89479.106254] [] ? _spin_unlock+0x1d/0x20 [89479.106270] [] ? __slab_alloc+0x550/0x560 [89479.106302] [] ? delay_tsc+0x17/0x24 [89479.106319] [] ? __const_udelay+0x21/0x30 [89479.106376] [] ? hermes_bap_seek+0x112/0x1e0 [hermes] [89479.106396] [] ? trace_hardirqs_off+0xb/0x10 [89479.106418] [] ? __kmalloc_track_caller+0xb7/0x110 [89479.106448] [] ? dev_alloc_skb+0x1c/0x30 [89479.106465] [] ? dev_alloc_skb+0x1c/0x30 [89479.106482] [] __list_add+0x8f/0xa0 [89479.106551] [] orinoco_interrupt+0xcae/0x16c0 [orinoco] [89479.106574] [] ? tick_dev_program_event+0x33/0xb0 [89479.106594] [] ? native_sched_clock+0x20/0x70 [89479.106613] [] ? lock_release_holdtime+0x35/0x200 [89479.106662] [] ? trace_hardirqs_off+0xb/0x10 [89479.106892] [] ? usb_hcd_irq+0x97/0xa0 [usbcore] [89479.106926] [] handle_IRQ_event+0x29/0x60 [89479.106947] [] handle_level_irq+0x69/0xe0 [89479.106963] [] ? handle_level_irq+0x0/0xe0 [89479.106977] [] ? tcp_v4_rcv+0x633/0x6e0 [89479.107025] [] ? common_interrupt+0x28/0x30 [89479.107057] [] ? sk_run_filter+0x320/0x7a0 [89479.107078] [] ? list_del+0x21/0x90 [89479.107106] [] ? orinoco_rx_isr_tasklet+0x2ce/0x480 [orinoco] [89479.107131] [] ? __lock_acquire+0x160/0x1650 [89479.107151] [] ? native_sched_clock+0x20/0x70 [89479.107169] [] ? lock_release_holdtime+0x35/0x200 [89479.107200] [] ? irq_enter+0xa/0x60 [89479.107217] [] ? do_IRQ+0xd2/0x130 [89479.107518] [] ? restore_nocheck_notrace+0x0/0xe [89479.107542] [] ? __do_softirq+0x0/0x110 [89479.107561] [] ? trace_hardirqs_on_caller+0x74/0x140 [89479.107583] [] ? trace_hardirqs_on_thunk+0xc/0x10 [89479.107602] [] ? tasklet_action+0x27/0x90 [89479.107620] [] ? trace_hardirqs_on_caller+0x74/0x140 [89479.107638] [] ? tasklet_action+0x43/0x90 [89479.107655] [] ? __do_softirq+0x6f/0x110 [89479.107674] [] ? __do_softirq+0x0/0x110 [89479.107685] [] ? handle_level_irq+0x0/0xe0 [89479.107715] [] ? irq_exit+0x5d/0x80 [89479.107732] [] ? do_IRQ+0xd2/0x130 [89479.107747] [] ? sysenter_exit+0xf/0x16 [89479.107765] [] ? trace_hardirqs_on_caller+0xfd/0x140 [89479.107782] [] ? common_interrupt+0x28/0x30 [89479.107797] ---[ end trace a1fc0a52df4a729d ]--- Reported-by: Andrey Borzenkov Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index bc84e2792f8a..c3bb85e0251e 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1610,6 +1610,16 @@ static void orinoco_rx_isr_tasklet(unsigned long data) struct orinoco_rx_data *rx_data, *temp; struct hermes_rx_descriptor *desc; struct sk_buff *skb; + unsigned long flags; + + /* orinoco_rx requires the driver lock, and we also need to + * protect priv->rx_list, so just hold the lock over the + * lot. + * + * If orinoco_lock fails, we've unplugged the card. In this + * case just abort. */ + if (orinoco_lock(priv, &flags) != 0) + return; /* extract desc and skb from queue */ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { @@ -1622,6 +1632,8 @@ static void orinoco_rx_isr_tasklet(unsigned long data) kfree(desc); } + + orinoco_unlock(priv, &flags); } /********************************************************************/ @@ -3645,12 +3657,22 @@ struct net_device void free_orinocodev(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_rx_data *rx_data, *temp; - /* No need to empty priv->rx_list: if the tasklet is scheduled - * when we call tasklet_kill it will run one final time, - * emptying the list */ + /* If the tasklet is scheduled when we call tasklet_kill it + * will run one final time. However the tasklet will only + * drain priv->rx_list if the hw is still available. */ tasklet_kill(&priv->rx_tasklet); + /* Explicitly drain priv->rx_list */ + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { + list_del(&rx_data->list); + + dev_kfree_skb(rx_data->skb); + kfree(rx_data->desc); + kfree(rx_data); + } + unregister_pm_notifier(&priv->pm_notifier); orinoco_uncache_fw(priv); -- cgit v1.2.3 From 86060f0d691f5ee1b4ef4efe770b683e54ac438d Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 7 Jan 2009 14:25:29 +0530 Subject: ath9k: Fix chainmask handling bug The chainmasks have to be updated before setting the channel, since the HW reset routine uses them to set the appropriate registers. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 191eec50dc75..727f067aca4f 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2164,13 +2164,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) conf->ht.channel_type); } + ath_update_chainmask(sc, conf->ht.enabled); + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } - - ath_update_chainmask(sc, conf->ht.enabled); } if (changed & IEEE80211_CONF_CHANGE_POWER) -- cgit v1.2.3 From d732129b25b972c208c9705759c8c64f63a21800 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 8 Jan 2009 10:20:00 -0800 Subject: iwlwifi: Fix get_cmd_string() for REPLY_3945_RX 0x1b is a 3945 specific command, we should print it too when debugging. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 01a2169cecec..8c71ad4f88c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_REMOVE_STA); IWL_CMD(REPLY_REMOVE_ALL_STA); IWL_CMD(REPLY_WEPKEY); + IWL_CMD(REPLY_3945_RX); IWL_CMD(REPLY_TX); IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); -- cgit v1.2.3 From 706ea9b66935e341b063d860c9c8f279b37b5578 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 9 Jan 2009 12:31:48 -0500 Subject: orinoco_cs: add ID for ARtem Onair Comcard 11 Reported by Michael Jarosch Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f127602670ec..0b32215d3f5d 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -435,6 +435,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ -- cgit v1.2.3 From c1d34c1dad76be6d515ef33e24eb92f10547b08b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 20 Dec 2008 02:21:37 +0100 Subject: p54: crypto offload fixes This patch fixes two small flaws: - restore the original TKIP IV if we altered it. - reserve & initialize ICV with zeros. This is actually only necessary for some obsolete p54usb firmwares. But we don't know yet, if all devices are compatible with the new revisions. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 06c64744df27..37294a657f8b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -809,6 +809,16 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; info->status.ack_signal = p54_rssi_to_dbm(dev, (int)payload->ack_rssi); + + if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { + u8 *iv = (u8 *)(entry_data->align + pad + + entry_data->crypt_offset); + + /* Restore the original TKIP IV. */ + iv[2] = iv[0]; + iv[0] = iv[1]; + iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ + } skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); ieee80211_tx_status_irqsafe(dev, entry); goto out; @@ -1394,7 +1404,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->tries = ridx; txhdr->rts_rate_idx = 0; if (info->control.hw_key) { - crypt_offset += info->control.hw_key->iv_len; txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); txhdr->key_len = min((u8)16, info->control.hw_key->keylen); memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); @@ -1408,6 +1417,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } /* reserve some space for ICV */ len += info->control.hw_key->icv_len; + memset(skb_put(skb, info->control.hw_key->icv_len), 0, + info->control.hw_key->icv_len); } else { txhdr->key_type = 0; txhdr->key_len = 0; -- cgit v1.2.3 From 00627f229c9807e4cb825a7ce36b886e2adf2229 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 20 Dec 2008 02:21:56 +0100 Subject: p54usb: fix random traffic stalls (LM87) All LM87 firmwares need a explicit termination "packet", in oder to finish the pending transfer properly. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 8f5c063b854b..6a6a72f6f82c 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -285,6 +285,7 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), skb->data, skb->len, p54u_tx_cb, skb); + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(data_urb, &priv->submitted); if (usb_submit_urb(data_urb, GFP_ATOMIC)) { -- cgit v1.2.3 From d15cfc3ac77388f1d588c57743d5f26b15eba9a8 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 11:00:23 +0100 Subject: rt2x00: Fix segementation fault The queue_end() macro points to 1 position after the queue, which means that if we want to know if queue is at the end of the queue we should first increment the position and then check if it is a valid entry. This fixes a segmentation fault which only occurs when the device has enough endpoints to provide a dedicated endpoint for all TX queues (which likely won't happen for rt2500usb and rt73usb, but will happen for rt2800usb). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 83df312ac56f..0b29d767a258 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -434,11 +434,11 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) if (usb_endpoint_is_bulk_in(ep_desc)) { rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); - } else if (usb_endpoint_is_bulk_out(ep_desc)) { + } else if (usb_endpoint_is_bulk_out(ep_desc) && + (queue != queue_end(rt2x00dev))) { rt2x00usb_assign_endpoint(queue, ep_desc); + queue = queue_next(queue); - if (queue != queue_end(rt2x00dev)) - queue = queue_next(queue); tx_ep_desc = ep_desc; } } -- cgit v1.2.3 From 1061787967db03975dc02030d6815811f4eb9231 Mon Sep 17 00:00:00 2001 From: Daniel Wu Date: Sat, 20 Dec 2008 10:53:29 -0800 Subject: iwlwifi: Fix typo in iwl-commands.h for CCK rate bit range. My first (minor) patch, hopefully this is correct. Fix a typo in iwl-commands.h for CCK rates which needs 7 bits and not 4. Signed-off-by: Daniel Wu Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 52966ffbef6e..ba997204c8d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -255,7 +255,7 @@ struct iwl_cmd_header { * 0x3) 54 Mbps * * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"): - * 3-0: 10) 1 Mbps + * 6-0: 10) 1 Mbps * 20) 2 Mbps * 55) 5.5 Mbps * 110) 11 Mbps -- cgit v1.2.3 From b55eae3349ff5d6d088c7ab0151260d5e3dbd26d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 21 Dec 2008 15:40:33 -0600 Subject: rtl8180: Fix to add STA mode To be compatible with mac80211 following "mac80211: only create default STA interface if supported", rtl8180 needs to set NL80211_IFTYPE_STATION in interface_modes. Signed-off-by: Larry Finger Reported-by: Fabio Rossi Tested-by: Piter PUNK Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 5f887fb137a9..387c133ec0f2 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -897,6 +897,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->queues = 1; dev->max_signal = 65; -- cgit v1.2.3 From f3d340c1d536fd3e5a104c99ac9c3f8694270d72 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 21 Dec 2008 23:19:17 +0100 Subject: Fix rt2500usb HW crypto: TKIP rt2500usb doesn't strip the IV/ICV data from received frames, so we don't need to set the RX_FLAG_IV_STRIPPED flag. We do need to set the RX_FLAG_MMIC_STRIPPED flag for all encryption types since the MMIC has been removed from the frame. After this patch TKIP Hardware crypto works for rt2500usb. WEP and AES are still failing. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 30028e2422fc..065f111f01fd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -376,11 +376,11 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, /* * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 + * in hardware. However it demands the data to be provided + * both seperately as well as inside the frame. + * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib + * to ensure rt2x00lib will not strip the data from the + * frame after the copy, now we must tell mac80211 * to generate the IV/EIV data. */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -1334,14 +1334,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, /* ICV is located at the end of frame */ - /* - * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. It has provided the data seperately but rt2x00lib - * should decide if it should be reinserted. - */ - rxdesc->flags |= RX_FLAG_IV_STRIPPED; - if (rxdesc->cipher != CIPHER_TKIP) - rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; + rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) rxdesc->flags |= RX_FLAG_DECRYPTED; else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) -- cgit v1.2.3 From d3a1db1c67735063921d9186145fc86164cf9781 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Mon, 22 Dec 2008 16:31:58 +0530 Subject: ath9k: Fix incorrect sequence numbering for unaggregated QoS Frame. This patch fixes an issue with the sequence numbers of unaggregated QoS frames, because of which the frames are handled in a different order at the AP and resulted in MLME REPLAYFAILURE. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 3bfc3b90f256..1ea9428c0cd2 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -264,25 +264,22 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb, } /* Get seqno */ - - if (ieee80211_is_data(fc) && !is_pae(skb)) { - /* For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - } + /* For HT capable stations, we save tidno for later use. + * We also override seqno set by upper layer with the one + * in tx aggregation state. + * + * If fragmentation is on, the sequence number is + * not overridden, since it has been + * incremented by the fragmentation routine. + * + * FIXME: check if the fragmentation threshold exceeds + * IEEE80211 max. + */ + tid = ATH_AN_2_TID(an, bf->bf_tidno); + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << + IEEE80211_SEQ_SEQ_SHIFT); + bf->bf_seqno = tid->seq_next; + INCR(tid->seq_next, IEEE80211_SEQ_MAX); } static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, @@ -1718,11 +1715,10 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, /* Assign seqno, tidno */ - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR)) + if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) assign_aggr_tid_seqno(skb, bf); /* DMA setup */ - bf->bf_mpdu = skb; bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, -- cgit v1.2.3 From 157ec8768457e8177d281ae099fb1c321c9a16d7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 22 Dec 2008 16:45:54 +0200 Subject: ath9k: Revert fix to TX status reporting for retries and MCS index This patch reverts "ath9k: Fix TX status reporting for retries and MCS index" because that change ended up breaking ath9k rate control. While the MCS index reporting to mac80211 was indeed fixed by the patch, it did not take into account that the ath9k rate control algorithm was updating private tables based on this index and the index comes through the rate control API call, i.e., based on mac80211 TX status call. In addition, it looks like the "fix" to remove +1 from TX status 'count' field was not correct based on ieee80211_tx_status() implementation that counts the total of count values, but starting from -1, not 0. The TX status reporting for frames using MCS needs to be fixed somehow, but it does not look like there is any easy fix for the ath9k rate control algorithm, so the best option now seems to be to revert the change and bring it back once the rate control code is cleaned up to handle this better. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/xmit.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 1ea9428c0cd2..c92f0c6e4adc 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -126,15 +126,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_info->flags |= IEEE80211_TX_STAT_ACK; } - tx_info->status.rates[0].count = tx_status->retries; - if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { - /* Change idx from internal table index to MCS index */ - int idx = tx_info->status.rates[0].idx; - struct ath_rate_table *rate_table = sc->cur_rate_table; - if (idx >= 0 && idx < rate_table->rate_cnt) - tx_info->status.rates[0].idx = - rate_table->info[idx].ratecode & 0x7f; - } + tx_info->status.rates[0].count = tx_status->retries + 1; hdrlen = ieee80211_get_hdrlen_from_skb(skb); padsize = hdrlen & 3; -- cgit v1.2.3 From 4fb7404e0eaf574c00d01d2b1ce2615229b350cd Mon Sep 17 00:00:00 2001 From: Steve Brown Date: Tue, 23 Dec 2008 07:57:05 -0500 Subject: ath5k: Correct usage of AR5K_CFG_ADHOC This corrects usage of AR5K_CFG_ADHOC introduced in "ath5k: Update PCU code". Also, the name of the indicator is changed to AR5K_CFG_IBSS to more accurately reflect its function. This change restores beaconing in AP and mesh modes. Signed-off-by: Steve Brown Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/pcu.c | 4 ++-- drivers/net/wireless/ath5k/reg.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 0cac05c6a9ce..75eb9f43c741 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -65,7 +65,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_AP: @@ -75,7 +75,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); + AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 91aaeaf88199..9189ab13286c 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -73,7 +73,7 @@ #define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ #define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ #define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ -#define AR5K_CFG_ADHOC 0x00000020 /* AP/Adhoc indication [5211+] */ +#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */ #define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ #define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ #define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ -- cgit v1.2.3 From 124b68e755c2ef9342d5d477142c499fd7901360 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 26 Dec 2008 19:09:45 +0100 Subject: p54: fix WARN_ON at line 2247 of net/mac80211/rx.c This patch hopefully fixes a mac80211<->p54 interaction problem, which was described by Larry Finger (ref: http://marc.info/?l=linux-wireless&m=123009889327707 ) I guess the warning was triggered by pending frames in the receive queue, while we're doing a band change 5GHz. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 37294a657f8b..cba89ed0f572 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -586,6 +586,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) u16 freq = le16_to_cpu(hdr->freq); size_t header_len = sizeof(*hdr); u32 tsf32; + u8 rate = hdr->rate & 0xf; /* * If the device is in a unspecified state we have to @@ -614,8 +615,11 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) rx_status.qual = (100 * hdr->rssi) / 127; if (hdr->rate & 0x10) rx_status.flag |= RX_FLAG_SHORTPRE; - rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? - hdr->rate : (hdr->rate - 4)) & 0xf; + if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) + rx_status.rate_idx = (rate < 4) ? 0 : rate - 4; + else + rx_status.rate_idx = rate; + rx_status.freq = freq; rx_status.band = dev->conf.channel->band; rx_status.antenna = hdr->antenna; -- cgit v1.2.3 From d6e2be988d5146d1faa8df895cd8b32106d987bd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Jan 2009 23:11:26 -0600 Subject: rtl8187: Fix module so that rmmod/insmod does not error Due to misunderstanding of the returned values allowed for the tx callback of mac80211, rtl8187 was using skb's that had been freed. This problem was triggered when the module was sujected to a rmmod/insmod cycle. After that was fixed, the modules would not work after the rmmod/insmod cycle until the USB device was reset. Signed-off-by: Johannes Berg Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 00ce3ef39abe..6ad6bac37706 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -213,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { kfree_skb(skb); - return -ENOMEM; + return NETDEV_TX_OK; } flags = skb->len; @@ -281,7 +281,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } usb_free_urb(urb); - return rc; + return NETDEV_TX_OK; } static void rtl8187_rx_cb(struct urb *urb) @@ -1471,6 +1471,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf) ieee80211_unregister_hw(dev); priv = dev->priv; + usb_reset_device(priv->udev); usb_put_dev(interface_to_usbdev(intf)); ieee80211_free_hw(dev); } -- cgit v1.2.3 From 71ef99c8b79ab07e1c79794085481464f9870d62 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 5 Jan 2009 20:46:34 -0500 Subject: ath5k: fix return values from ath5k_tx Should return NETDEV_TX_{OK,BUSY} instead of 0,-1 (this doesn't change any current functionality). Changes-licensed-under: 3-Clause-BSD Reported-by: Johannes Berg Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 4af2607deec0..8ef87356e083 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2644,7 +2644,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (skb_headroom(skb) < padsize) { ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" " headroom to pad %d\n", hdrlen, padsize); - return -1; + return NETDEV_TX_BUSY; } skb_push(skb, padsize); memmove(skb->data, skb->data+padsize, hdrlen); @@ -2655,7 +2655,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); spin_unlock_irqrestore(&sc->txbuflock, flags); ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - return -1; + return NETDEV_TX_BUSY; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); list_del(&bf->list); @@ -2673,10 +2673,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) sc->txbuf_len++; spin_unlock_irqrestore(&sc->txbuflock, flags); dev_kfree_skb_any(skb); - return 0; + return NETDEV_TX_OK; } - return 0; + return NETDEV_TX_OK; } static int -- cgit v1.2.3 From f1dd2b23badfe8a28910a78be24452c627c4b6f2 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 3 Jan 2009 16:27:14 +0100 Subject: rt2x00: Fix rt2500usb HW crypto: WEP 128 & AES The TXD_W0_CIPHER field is a 1-bit field. It only acts as boolean value to indicate if the frame must be encrypted or not. The way rt2x00_set_field32() worked it would grab the least signifcant bit from txdesc->cipher and use that as value. Because of that WEP 64 and TKIP worked since they had odd-numbered values, while WEP 128 and AES were even numbers and didn't work. Correctly booleanize the txdecs->cipher value to allow the hardware to encrypt the outgoing data. After this we can enable HW crypto by default again. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 065f111f01fd..af6b5847be5c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -38,7 +38,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 1; +static int modparam_nohwcrypt = 0; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -1181,7 +1181,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher); + rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); rt2x00_desc_write(txd, 0, word); } -- cgit v1.2.3 From 51e99158d261a5ec5772ca89b935c3daa270b07c Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky Date: Mon, 5 Jan 2009 14:37:31 -0800 Subject: libertas_tf: return NETDEV_TX_OK in TX op The TX op should return NETDEV_TX_OK or NETDEV_TX_BUSY. Signed-off-by: Andrey Yurovsky Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index d1fc305de5fe..e7289e2e7f16 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -206,7 +206,7 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * there are no buffered multicast frames to send */ ieee80211_stop_queues(priv->hw); - return 0; + return NETDEV_TX_OK; } static void lbtf_tx_work(struct work_struct *work) -- cgit v1.2.3 From fe333321e2a71f706b794d55b6a3dcb5ab240f65 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 6 Jan 2009 14:26:03 +0000 Subject: powerpc: Change u64/s64 to a long long integer type Convert arch/powerpc/ over to long long based u64: -#ifdef __powerpc64__ -# include -#else -# include -#endif +#include This will avoid reoccuring spurious warnings in core kernel code that comes when people test on their own hardware. (i.e. x86 in ~98% of the cases) This is what x86 uses and it generally helps keep 64-bit code 32-bit clean too. [Adjusted to not impact user mode (from paulus) - sfr] Signed-off-by: Ingo Molnar Signed-off-by: Stephen Rothwell Signed-off-by: Benjamin Herrenschmidt --- drivers/net/pasemi_mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 5b7a574ce571..d0349e7d73ea 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -712,7 +712,7 @@ static inline void pasemi_mac_rx_error(const struct pasemi_mac *mac, rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno)); - printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n", + printk(KERN_ERR "pasemi_mac: rx error. macrx %016llx, rx status %llx\n", macrx, *chan->status); printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n", @@ -730,8 +730,8 @@ static inline void pasemi_mac_tx_error(const struct pasemi_mac *mac, cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno)); - printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\ - "tx status 0x%016lx\n", mactx, *chan->status); + printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016llx, "\ + "tx status 0x%016llx\n", mactx, *chan->status); printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta); } -- cgit v1.2.3 From a1c5a8932bbb75b550deb156d890027827fc9d6e Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 6 Jan 2009 14:40:06 +0000 Subject: powerpc: Cleanup from l64 to ll64 change: drivers/net These are powerpc specific drivers. Signed-off-by: Stephen Rothwell Acked-by: David S. Miller Signed-off-by: Benjamin Herrenschmidt --- drivers/net/ehea/ehea_main.c | 8 ++++---- drivers/net/ehea/ehea_qmr.c | 18 +++++++++--------- drivers/net/ibmveth.c | 16 ++++++++-------- drivers/net/iseries_veth.c | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index e3131ea629cd..dfe92264e825 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -132,7 +132,7 @@ void ehea_dump(void *adr, int len, char *msg) int x; unsigned char *deb = adr; for (x = 0; x < len; x += 16) { - printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg, + printk(DRV_NAME " %s adr=%p ofs=%04x %016llx %016llx\n", msg, deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8])); deb += 16; } @@ -883,7 +883,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param) while (eqe) { qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry); - ehea_error("QP aff_err: entry=0x%lx, token=0x%x", + ehea_error("QP aff_err: entry=0x%llx, token=0x%x", eqe->entry, qp_token); qp = port->port_res[qp_token].qp; @@ -1159,7 +1159,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe) netif_stop_queue(port->netdev); break; default: - ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe); + ehea_error("unknown event code %x, eqe=0x%llX", ec, eqe); break; } } @@ -1971,7 +1971,7 @@ static void ehea_set_multicast_list(struct net_device *dev) } if (dev->mc_count > port->adapter->max_mc_mac) { - ehea_info("Mcast registration limit reached (0x%lx). " + ehea_info("Mcast registration limit reached (0x%llx). " "Use ALLMULTI!", port->adapter->max_mc_mac); goto out; diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 225c692b5d99..49d766ebbcf4 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -168,7 +168,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, cq->fw_handle, rpage, 1); if (hret < H_SUCCESS) { ehea_error("register_rpage_cq failed ehea_cq=%p " - "hret=%lx counter=%i act_pages=%i", + "hret=%llx counter=%i act_pages=%i", cq, hret, counter, cq->attr.nr_pages); goto out_kill_hwq; } @@ -178,13 +178,13 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, if ((hret != H_SUCCESS) || (vpage)) { ehea_error("registration of pages not " - "complete hret=%lx\n", hret); + "complete hret=%llx\n", hret); goto out_kill_hwq; } } else { if (hret != H_PAGE_REGISTERED) { ehea_error("CQ: registration of page failed " - "hret=%lx\n", hret); + "hret=%llx\n", hret); goto out_kill_hwq; } } @@ -986,15 +986,15 @@ void print_error_data(u64 *data) length = EHEA_PAGESIZE; if (type == 0x8) /* Queue Pair */ - ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, " - "port=%lX", resource, data[6], data[12], data[22]); + ehea_error("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, " + "port=%llX", resource, data[6], data[12], data[22]); if (type == 0x4) /* Completion Queue */ - ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource, + ehea_error("CQ (resource=%llX) state: AER=0x%llX", resource, data[6]); if (type == 0x3) /* Event Queue */ - ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource, + ehea_error("EQ (resource=%llX) state: AER=0x%llX", resource, data[6]); ehea_dump(data, length, "error data"); @@ -1016,11 +1016,11 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) rblock); if (ret == H_R_STATE) - ehea_error("No error data is available: %lX.", res_handle); + ehea_error("No error data is available: %llX.", res_handle); else if (ret == H_SUCCESS) print_error_data(rblock); else - ehea_error("Error data could not be fetched: %lX", res_handle); + ehea_error("Error data could not be fetched: %llX", res_handle); kfree(rblock); } diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index ca3bb9f7321b..dfa6348ac1dc 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -602,7 +602,7 @@ static int ibmveth_open(struct net_device *netdev) if(lpar_rc != H_SUCCESS) { ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); - ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n", + ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n", adapter->buffer_list_dma, adapter->filter_list_dma, rxq_desc.desc, @@ -1378,13 +1378,13 @@ static int ibmveth_show(struct seq_file *seq, void *v) seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac); seq_printf(seq, "\nAdapter Statistics:\n"); - seq_printf(seq, " TX: vio_map_single failres: %ld\n", adapter->tx_map_failed); - seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed); - seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles); - seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem); - seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); - seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); - seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); + seq_printf(seq, " TX: vio_map_single failres: %lld\n", adapter->tx_map_failed); + seq_printf(seq, " send failures: %lld\n", adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %lld\n", adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %lld\n", adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %lld\n", adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %lld\n", adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %lld\n", adapter->rx_no_buffer); return 0; } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index c7457f97259d..cb793c2bade2 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -429,7 +429,7 @@ SIMPLE_PORT_ATTR(promiscuous); SIMPLE_PORT_ATTR(num_mcast); CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map); CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map); -CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr); +CUSTOM_PORT_ATTR(mac_addr, "0x%llX\n", port->mac_addr); #define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr) static struct attribute *veth_port_default_attrs[] = { -- cgit v1.2.3 From d9736749f581abd80c2831244e2659e2e833b0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= Date: Mon, 12 Jan 2009 16:31:54 -0800 Subject: WAN: Fix NAPI interface in IXP4xx HSS driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Hałasa Signed-off-by: David S. Miller --- drivers/net/wan/ixp4xx_hss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 2dc241689d37..0dbd85b0162d 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev) printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); #endif qmgr_disable_irq(queue_ids[port->id].rx); - netif_rx_schedule(dev, &port->napi); + netif_rx_schedule(&port->napi); } static int hss_hdlc_poll(struct napi_struct *napi, int budget) @@ -651,7 +651,7 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget) printk(KERN_DEBUG "%s: hss_hdlc_poll" " netif_rx_complete\n", dev->name); #endif - netif_rx_complete(dev, napi); + netif_rx_complete(napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && netif_rx_reschedule(napi)) { @@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev) hss_start_hdlc(port); /* we may already have RX data, enables IRQ */ - netif_rx_schedule(dev, &port->napi); + netif_rx_schedule(&port->napi); return 0; err_unlock: -- cgit v1.2.3 From b74f62c1e736ea01c660355526dd54132d241ca9 Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Mon, 12 Jan 2009 21:56:49 -0800 Subject: hso: driver fix for big endian machines. Filip Aben says this fix is neccessary for big endian machines. Signed-off-by: Denis Joseph Barrow Signed-off-by: David S. Miller --- drivers/net/usb/hso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index c4918b86ed19..d17dc5214c9a 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1792,8 +1792,8 @@ static int mux_device_request(struct hso_serial *serial, u8 type, u16 port, /* initialize */ ctrl_req->wValue = 0; - ctrl_req->wIndex = hso_port_to_mux(port); - ctrl_req->wLength = size; + ctrl_req->wIndex = cpu_to_le16(hso_port_to_mux(port)); + ctrl_req->wLength = cpu_to_le16(size); if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) { /* Reading command */ -- cgit v1.2.3 From a6d0b91ae5dd01263530c96f9b29001cb1ed58b0 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 12 Jan 2009 21:57:34 -0800 Subject: gianfar: Fix soft lockup with multi-interrupt TSECs This patch fixes following bug: BUG: soft lockup - CPU#0 stuck for 61s! [S03mountvirtfs-:922] Modules linked in: NIP: c006505c LR: c00675f0 CTR: c0020438 REGS: c7a1db90 TRAP: 0901 Not tainted (2.6.28-rc8-01311-g8c7396a) MSR: 00009032 CR: 28248442 XER: 20000000 TASK = c7a288a0[922] 'S03mountvirtfs-' THREAD: c7a1c000 GPR00: 00009032 c7a1dc40 c7a288a0 00000024 c79a1840 00000000 00000300 00000020 GPR08: c035f97c 00000000 00004008 c04d5210 00000000 NIP [c006505c] handle_IRQ_event+0x34/0xb0 LR [c00675f0] handle_level_irq+0xa8/0x144 Call Trace: [c7a1dc40] [c00204d8] ipic_mask_irq+0xa0/0xb4 (unreliable) [c7a1dc60] [c00675f0] handle_level_irq+0xa8/0x144 [c7a1dc80] [c00067f8] do_IRQ+0x78/0x108 [c7a1dc90] [c0014d7c] ret_from_except+0x0/0x14 --- Exception: 501 at gfar_schedule_cleanup+0x54/0x7c LR = gfar_transmit+0x14/0x28 [c7a1dd50] [c0352a3c] _spin_unlock_irqrestore+0x18/0x30 (unreliable) [c7a1dd60] [c01f49a8] gfar_transmit+0x14/0x28 [c7a1dd70] [c0065084] handle_IRQ_event+0x5c/0xb0 [c7a1dd90] [c00675f0] handle_level_irq+0xa8/0x144 [c7a1ddb0] [c00067f8] do_IRQ+0x78/0x108 [c7a1ddc0] [c0014d7c] ret_from_except+0x0/0x14 --- Exception: 501 at up_read+0x10/0x48 LR = do_page_fault+0x2b0/0x3e0 [c7a1de80] [c7a177e8] 0xc7a177e8 (unreliable) [c7a1de90] [c0017964] do_page_fault+0x2b0/0x3e0 [c7a1df40] [c0014b14] handle_page_fault+0xc/0x80 --- Exception: 301 at 0xfe98b7c LR = 0xfe989c0 Instruction dump: 7c0802a6 bf810010 7c9f2378 7c7c1b78 90010024 80040004 70090020 40820010 7c0000a6 60008000 7c000124 3bc00000 <3ba00000> 48000010 83ff0014 2f9f0000 The bug introduced by commit 8c7396aebb68994c0519e438eecdf4d5fa9c7844 ("gianfar: Merge Tx and Rx interrupt for scheduling clean up ring"). The commit merged TX and RX interrupt code into a single routine that schedules NAPI, but no locks were introduced. This causes irq races, so when irqs are enabled and netif_rx_schedule_prep() returns 0, nobody disable the interrupts again. This leads to interrupt storm and finally to the lockup. Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index efcbeb6c8673..ea530673236e 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1622,10 +1622,18 @@ static int gfar_clean_tx_ring(struct net_device *dev) static void gfar_schedule_cleanup(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->txlock, flags); + spin_lock(&priv->rxlock); + if (netif_rx_schedule_prep(&priv->napi)) { gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED); __netif_rx_schedule(&priv->napi); } + + spin_unlock(&priv->rxlock); + spin_unlock_irqrestore(&priv->txlock, flags); } /* Interrupt Handler for Transmit complete */ -- cgit v1.2.3 From 859975764fa61e927e7a69f46a55a4ba415785dd Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 12 Jan 2009 22:11:56 -0800 Subject: net: ppp_generic - fix regressions caused by IDR conversion The commits: 7a95d267fb62cd6b80ef73be0592bbbe1dbd5df7 ("net: ppp_generic - use idr technique instead of cardmaps") ab5024ab23b78c86a0a1425defcdde48710fe449 ("net: ppp_generic - use DEFINE_IDR for static initialization") introduced usage of IDR functionality but broke userspace side. Before this commits it was possible to allocate new ppp interface with specified number. Now it fails with EINVAL. Fix it by trying to allocate interface with specified unit number and return EEXIST if fail which allow pppd to ask us to allocate new unit number. And fix messages on memory allocation fails - add details that it's PPP module who is complaining. Signed-off-by: Cyrill Gorcunov Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 06b448285eb5..7b2728b8f1b7 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -250,6 +250,7 @@ static int ppp_connect_channel(struct channel *pch, int unit); static int ppp_disconnect_channel(struct channel *pch); static void ppp_destroy_channel(struct channel *pch); static int unit_get(struct idr *p, void *ptr); +static int unit_set(struct idr *p, void *ptr, int n); static void unit_put(struct idr *p, int n); static void *unit_find(struct idr *p, int n); @@ -2432,11 +2433,18 @@ ppp_create_interface(int unit, int *retp) } else { if (unit_find(&ppp_units_idr, unit)) goto out2; /* unit already exists */ - else { - /* darn, someone is cheating us? */ - *retp = -EINVAL; + /* + * if caller need a specified unit number + * lets try to satisfy him, otherwise -- + * he should better ask us for new unit number + * + * NOTE: yes I know that returning EEXIST it's not + * fair but at least pppd will ask us to allocate + * new unit in this case so user is happy :) + */ + unit = unit_set(&ppp_units_idr, ppp, unit); + if (unit < 0) goto out2; - } } /* Initialize the new ppp unit */ @@ -2677,14 +2685,37 @@ static void __exit ppp_cleanup(void) * by holding all_ppp_mutex */ +/* associate pointer with specified number */ +static int unit_set(struct idr *p, void *ptr, int n) +{ + int unit, err; + +again: + if (!idr_pre_get(p, GFP_KERNEL)) { + printk(KERN_ERR "PPP: No free memory for idr\n"); + return -ENOMEM; + } + + err = idr_get_new_above(p, ptr, n, &unit); + if (err == -EAGAIN) + goto again; + + if (unit != n) { + idr_remove(p, unit); + return -EINVAL; + } + + return unit; +} + /* get new free unit number and associate pointer with it */ static int unit_get(struct idr *p, void *ptr) { int unit, err; again: - if (idr_pre_get(p, GFP_KERNEL) == 0) { - printk(KERN_ERR "Out of memory expanding drawable idr\n"); + if (!idr_pre_get(p, GFP_KERNEL)) { + printk(KERN_ERR "PPP: No free memory for idr\n"); return -ENOMEM; } -- cgit v1.2.3 From 922d8a0b6d82fb40ffb561576e3800c3784ff43d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 12 Jan 2009 14:40:20 -0500 Subject: =?UTF-8?q?b43:=20fix=20"=E2=80=98gmode=E2=80=99=20may=20be=20used?= =?UTF-8?q?=20uninitialized"=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/b43/main.c: In function ‘b43_op_config’: drivers/net/wireless/b43/main.c:3264: warning: ‘gmode’ may be used uninitialized Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7b31a327b24a..c788bad10661 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3261,7 +3261,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) struct b43_wldev *down_dev; struct b43_wldev *d; int err; - bool gmode; + bool uninitialized_var(gmode); int prev_status; /* Find a device and PHY which supports the band. */ -- cgit v1.2.3 From 08cb7e01678b0a8d95d76aa0a395f2d7390f7ee1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 12 Jan 2009 14:43:18 -0500 Subject: =?UTF-8?q?b43legacy:=20fix=20"=E2=80=98up=5Fdev=E2=80=99=20may=20?= =?UTF-8?q?be=20used=20uninitialized"=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/b43legacy/main.c: In function ‘b43legacy_op_dev_config’: drivers/net/wireless/b43legacy/main.c:2468: warning: ‘up_dev’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c1324e31d2f6..fb996c27a19b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2465,7 +2465,7 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev) static int b43legacy_switch_phymode(struct b43legacy_wl *wl, unsigned int new_mode) { - struct b43legacy_wldev *up_dev; + struct b43legacy_wldev *uninitialized_var(up_dev); struct b43legacy_wldev *down_dev; int err; bool gmode = 0; -- cgit v1.2.3 From 25a4cceaa44a7f73c8f92e6177812347500a0b15 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 12 Jan 2009 14:44:52 -0500 Subject: =?UTF-8?q?iwl3945:=20fix=20"=E2=80=98power=5Fidx=E2=80=99=20may?= =?UTF-8?q?=20be=20used=20uninitialized"=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/iwlwifi/iwl-3945.c: In function ‘iwl3945_txpower_set_from_eeprom’: drivers/net/wireless/iwlwifi/iwl-3945.c:2222: warning: ‘power_idx’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8fdb34222c0a..45cfa1cf194a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2219,7 +2219,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) /* set tx power value for all OFDM rates */ for (rate_index = 0; rate_index < IWL_OFDM_RATES; rate_index++) { - s32 power_idx; + s32 uninitialized_var(power_idx); int rc; /* use channel group's clip-power table, -- cgit v1.2.3 From 26d1597c9a4532eec74f9651c4c96483cb8892fe Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 12 Jan 2009 14:46:39 -0500 Subject: =?UTF-8?q?p54:=20fix=20"=E2=80=98ret=E2=80=99=20may=20be=20used?= =?UTF-8?q?=20uninitialized"=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/p54/p54common.c: In function ‘p54_config’: drivers/net/wireless/p54/p54common.c:1853: warning: ‘ret’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index cba89ed0f572..c6a370fa9bcb 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1850,7 +1850,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev, static int p54_config(struct ieee80211_hw *dev, u32 changed) { - int ret; + int ret = 0; struct p54_common *priv = dev->priv; struct ieee80211_conf *conf = &dev->conf; -- cgit v1.2.3 From 483a2b3a3182abcb7fcea986d7ea13e793bb00b1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Jan 2009 14:35:15 -0800 Subject: ARM etherh: Fix build failure. Reported by Russell King: drivers/net/arm/etherh.c:649: error: unknown field 'ndo_set_mac_addr' specified in initializer Signed-off-by: David S. Miller --- drivers/net/arm/etherh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 745ac188babe..d15d8b79d8e5 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_addr = eth_set_mac_addr, + .ndo_set_mac_address = eth_set_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, -- cgit v1.2.3 From f0d44ae310bc8eb0b6694e257015d8b24e1a357c Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 14 Jan 2009 14:38:02 -0800 Subject: phylib: Fix Freescale TBI PHY detection Freescale on-chip TBI PHYs reports PHY ID as 0x0, but as of commit 3ee82383f0098a2e13acc8cf1be8e47512f41e5a Author: Giulio Benetti Date: Thu Nov 13 21:53:13 2008 +0000 phy: fix phy address bug PHYID returns 0xffff and not 0xffffffff when not found and in some case(at91sam9263) 0x0. Maybe this patch could be useful. phy_device.c treats PHY ID == 0x0 as bogus IDs, and that results in gianfar driver failure to see the TBI PHYs. This code snippet triggers: if (!priv->tbiphy) { printk(KERN_WARNING "SGMII mode requires that the device " "tree specify a tbi-handle\n"); return; } Although tbi-handle is specified in the device tree. Btw, technically PHY ID == 0x0 is a valid ID (if we ever see a PHY manufactured by Xerox :-). Signed-off-by: Anton Vorontsov Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e35460165bf7..0a06e4fd37d9 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -231,15 +231,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) if ((phy_id & 0x1fffffff) == 0x1fffffff) return NULL; - /* - * Broken hardware is sometimes missing the pull-up resistor on the - * MDIO line, which results in reads to non-existent devices returning - * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent - * device as well. - */ - if (phy_id == 0) - return NULL; - dev = phy_device_create(bus, addr, phy_id); return dev; -- cgit v1.2.3 From d7e094d4212bc72f5575e54edfef1349e0c4cdb5 Mon Sep 17 00:00:00 2001 From: Mike Ditto Date: Wed, 14 Jan 2009 20:43:43 -0800 Subject: powerpc/fs_enet: Add missing irq free in error path. If something goes wrong attaching to phy driver, we weren't freeing the IRQ. Signed-off-by: Mike Ditto Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 4e6a9195fe5f..ce900e54d8d1 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -795,6 +795,7 @@ static int fs_enet_open(struct net_device *dev) err = fs_init_phy(dev); if (err) { + free_irq(fep->interrupt, dev); if (fep->fpi->use_napi) napi_disable(&fep->napi); return err; -- cgit v1.2.3 From d1d5e6b1cead3df6f722d1d458874bd7f93da8d6 Mon Sep 17 00:00:00 2001 From: Daniele Venzano Date: Wed, 14 Jan 2009 20:46:24 -0800 Subject: sis900: generate fake MAC address if the hardware doesn't have one The attached patch modifies the sis900 driver when the MAC address read from the hardware is invalid. As suggested, the patch now generates a random address so that the user can go on and use the hardware. In any case a message is also shown to warn on the unexpected condition. This seems to happen with newer HW implementation of the sis900 chipset, since this never came up before. Patch is against vanilla 2.6.28 (but the driver doesn't change so often, so it will probably apply to older/newer versions too). See bugzilla ID 10201 and 11649 and ignore the previous patch. Signed-off-by: Daniele Venzano Signed-off-by: David S. Miller --- drivers/net/sis900.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 6cbefcae9ac2..be4465bc0a69 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -509,10 +509,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, else ret = sis900_get_mac_addr(pci_dev, net_dev); - if (ret == 0) { - printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name); - ret = -ENODEV; - goto err_unmap_rx; + if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) { + random_ether_addr(net_dev->dev_addr); + printk(KERN_WARNING "%s: Unreadable or invalid MAC address," + "using random generated one\n", dev_name); } /* 630ET : set the mii access mode as software-mode */ -- cgit v1.2.3 From 2edbb454428729f450f7a0aabbf95ac62b46b78a Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:47:30 -0800 Subject: netxen: fix endianness in firmware commands o Set restricted (little endian) data types in firmware command requests and responses. o Remove unnecessary conversion to LE when writing registers. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 98 ++++++++++++++++++------------------ drivers/net/netxen/netxen_nic_ctx.c | 50 ++++++++---------- drivers/net/netxen/netxen_nic_hw.c | 42 +++++++++------- drivers/net/netxen/netxen_nic_init.c | 2 +- 4 files changed, 95 insertions(+), 97 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f8e601c51da7..31311cc66d18 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -995,31 +995,31 @@ struct netxen_recv_context { */ typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u32 ring_size; /* Ring entries */ - u16 msi_index; - u16 rsvd; /* Padding */ + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le16 msi_index; + __le16 rsvd; /* Padding */ } nx_hostrq_sds_ring_t; typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u64 buff_size; /* Packet buffer size */ - u32 ring_size; /* Ring entries */ - u32 ring_kind; /* Class of ring */ + __le64 host_phys_addr; /* Ring base addr */ + __le64 buff_size; /* Packet buffer size */ + __le32 ring_size; /* Ring entries */ + __le32 ring_kind; /* Class of ring */ } nx_hostrq_rds_ring_t; typedef struct { - u64 host_rsp_dma_addr; /* Response dma'd here */ - u32 capabilities[4]; /* Flag bit vector */ - u32 host_int_crb_mode; /* Interrupt crb usage */ - u32 host_rds_crb_mode; /* RDS crb usage */ + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 host_rds_crb_mode; /* RDS crb usage */ /* These ring offsets are relative to data[0] below */ - u32 rds_ring_offset; /* Offset to RDS config */ - u32 sds_ring_offset; /* Offset to SDS config */ - u16 num_rds_rings; /* Count of RDS rings */ - u16 num_sds_rings; /* Count of SDS rings */ - u16 rsvd1; /* Padding */ - u16 rsvd2; /* Padding */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ u8 reserved[128]; /* reserve space for future expansion*/ /* MUST BE 64-bit aligned. The following is packed: @@ -1029,24 +1029,24 @@ typedef struct { } nx_hostrq_rx_ctx_t; typedef struct { - u32 host_producer_crb; /* Crb to use */ - u32 rsvd1; /* Padding */ + __le32 host_producer_crb; /* Crb to use */ + __le32 rsvd1; /* Padding */ } nx_cardrsp_rds_ring_t; typedef struct { - u32 host_consumer_crb; /* Crb to use */ - u32 interrupt_crb; /* Crb to use */ + __le32 host_consumer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ } nx_cardrsp_sds_ring_t; typedef struct { /* These ring offsets are relative to data[0] below */ - u32 rds_ring_offset; /* Offset to RDS config */ - u32 sds_ring_offset; /* Offset to SDS config */ - u32 host_ctx_state; /* Starting State */ - u32 num_fn_per_port; /* How many PCI fn share the port */ - u16 num_rds_rings; /* Count of RDS rings */ - u16 num_sds_rings; /* Count of SDS rings */ - u16 context_id; /* Handle for context */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le32 host_ctx_state; /* Starting State */ + __le32 num_fn_per_port; /* How many PCI fn share the port */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 context_id; /* Handle for context */ u8 phys_port; /* Physical id of port */ u8 virt_port; /* Virtual/Logical id of port */ u8 reserved[128]; /* save space for future expansion */ @@ -1072,34 +1072,34 @@ typedef struct { */ typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u32 ring_size; /* Ring entries */ - u32 rsvd; /* Padding */ + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le32 rsvd; /* Padding */ } nx_hostrq_cds_ring_t; typedef struct { - u64 host_rsp_dma_addr; /* Response dma'd here */ - u64 cmd_cons_dma_addr; /* */ - u64 dummy_dma_addr; /* */ - u32 capabilities[4]; /* Flag bit vector */ - u32 host_int_crb_mode; /* Interrupt crb usage */ - u32 rsvd1; /* Padding */ - u16 rsvd2; /* Padding */ - u16 interrupt_ctl; - u16 msi_index; - u16 rsvd3; /* Padding */ + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le64 cmd_cons_dma_addr; /* */ + __le64 dummy_dma_addr; /* */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ + __le16 interrupt_ctl; + __le16 msi_index; + __le16 rsvd3; /* Padding */ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */ u8 reserved[128]; /* future expansion */ } nx_hostrq_tx_ctx_t; typedef struct { - u32 host_producer_crb; /* Crb to use */ - u32 interrupt_crb; /* Crb to use */ + __le32 host_producer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ } nx_cardrsp_cds_ring_t; typedef struct { - u32 host_ctx_state; /* Starting state */ - u16 context_id; /* Handle for context */ + __le32 host_ctx_state; /* Starting state */ + __le16 context_id; /* Handle for context */ u8 phys_port; /* Physical id of port */ u8 virt_port; /* Virtual/Logical id of port */ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */ @@ -1202,9 +1202,9 @@ enum { #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ typedef struct { - u64 qhdr; - u64 req_hdr; - u64 words[6]; + __le64 qhdr; + __le64 req_hdr; + __le64 words[6]; } nx_nic_req_t; typedef struct { diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 64b51643c626..746bdb470418 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -76,7 +76,7 @@ netxen_api_unlock(struct netxen_adapter *adapter) static u32 netxen_poll_rsp(struct netxen_adapter *adapter) { - u32 raw_rsp, rsp = NX_CDRP_RSP_OK; + u32 rsp = NX_CDRP_RSP_OK; int timeout = 0; do { @@ -86,10 +86,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter) if (++timeout > NX_OS_CRB_RETRY_COUNT) return NX_CDRP_RSP_TIMEOUT; - netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, - &raw_rsp); - - rsp = le32_to_cpu(raw_rsp); + netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp); } while (!NX_CDRP_IS_RSP(rsp)); return rsp; @@ -109,20 +106,16 @@ netxen_issue_cmd(struct netxen_adapter *adapter, if (netxen_api_lock(adapter)) return NX_RCODE_TIMEOUT; - netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, - cpu_to_le32(signature)); + netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature); - netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, - cpu_to_le32(arg1)); + netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1); - netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, - cpu_to_le32(arg2)); + netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2); - netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, - cpu_to_le32(arg3)); + netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3); netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET, - cpu_to_le32(NX_CDRP_FORM_CMD(cmd))); + NX_CDRP_FORM_CMD(cmd)); rsp = netxen_poll_rsp(adapter); @@ -133,7 +126,6 @@ netxen_issue_cmd(struct netxen_adapter *adapter, rcode = NX_RCODE_TIMEOUT; } else if (rsp == NX_CDRP_RSP_FAIL) { netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode); - rcode = le32_to_cpu(rcode); printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); @@ -183,7 +175,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) int i, nrds_rings, nsds_rings; size_t rq_size, rsp_size; - u32 cap, reg; + u32 cap, reg, val; int err; @@ -225,11 +217,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq->num_rds_rings = cpu_to_le16(nrds_rings); prq->num_sds_rings = cpu_to_le16(nsds_rings); - prq->rds_ring_offset = 0; - prq->sds_ring_offset = prq->rds_ring_offset + + prq->rds_ring_offset = cpu_to_le32(0); + + val = le32_to_cpu(prq->rds_ring_offset) + (sizeof(nx_hostrq_rds_ring_t) * nrds_rings); + prq->sds_ring_offset = cpu_to_le32(val); - prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset); + prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + + le32_to_cpu(prq->rds_ring_offset)); for (i = 0; i < nrds_rings; i++) { @@ -241,17 +236,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); } - prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset); + prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + + le32_to_cpu(prq->sds_ring_offset)); prq_sds[0].host_phys_addr = cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count); /* only one msix vector for now */ - prq_sds[0].msi_index = cpu_to_le32(0); - - /* now byteswap offsets */ - prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset); - prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset); + prq_sds[0].msi_index = cpu_to_le16(0); phys_addr = hostrq_phys_addr; err = netxen_issue_cmd(adapter, @@ -269,9 +261,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prsp_rds = ((nx_cardrsp_rds_ring_t *) - &prsp->data[prsp->rds_ring_offset]); + &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); - for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) { + for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { rds_ring = &recv_ctx->rds_rings[i]; reg = le32_to_cpu(prsp_rds[i].host_producer_crb); @@ -279,7 +271,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) } prsp_sds = ((nx_cardrsp_sds_ring_t *) - &prsp->data[prsp->sds_ring_offset]); + &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); reg = le32_to_cpu(prsp_sds[0].host_consumer_crb); recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); @@ -288,7 +280,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); recv_ctx->context_id = le16_to_cpu(prsp->context_id); - recv_ctx->virt_port = le16_to_cpu(prsp->virt_port); + recv_ctx->virt_port = prsp->virt_port; out_free_rsp: pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index aa6e603bfcbf..e8a0eed0078e 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -539,16 +539,19 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev, { struct netxen_adapter *adapter = netdev_priv(dev); nx_nic_req_t req; - nx_mac_req_t mac_req; + nx_mac_req_t *mac_req; + u64 word; int rv; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_NIC_REQUEST << 23); - req.req_hdr |= NX_MAC_EVENT; - req.req_hdr |= ((u64)adapter->portnum << 16); - mac_req.op = op; - memcpy(&mac_req.mac_addr, addr, 6); - req.words[0] = cpu_to_le64(*(u64 *)&mac_req); + req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); + + word = NX_MAC_EVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + mac_req = (nx_mac_req_t *)&req.words[0]; + mac_req->op = op; + memcpy(mac_req->mac_addr, addr, 6); rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) { @@ -612,12 +615,16 @@ send_fw_cmd: int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) { nx_nic_req_t req; + u64 word; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_HOST_REQUEST << 23); - req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE; - req.req_hdr |= ((u64)adapter->portnum << 16); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(mode); return netxen_send_cmd_descs(adapter, @@ -632,13 +639,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) int netxen_config_intr_coalesce(struct netxen_adapter *adapter) { nx_nic_req_t req; + u64 word; int rv; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_NIC_REQUEST << 23); - req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE; - req.req_hdr |= ((u64)adapter->portnum << 16); + req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); + + word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal)); @@ -772,13 +781,10 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); - mac_hi = cpu_to_le32(mac_hi); - mac_lo = cpu_to_le32(mac_lo); - if (pci_func & 1) - *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16)); + *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); else - *mac = ((mac_lo) | ((u64)mac_hi << 32)); + *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32)); return 0; } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index d924468e506e..c0e06a653170 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1277,7 +1277,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, dev_kfree_skb_any(skb); for (i = 0; i < nr_frags; i++) { - index = frag_desc->frag_handles[i]; + index = le16_to_cpu(frag_desc->frag_handles[i]); skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (skb) -- cgit v1.2.3 From 391587c3447d99b842a647f8e701895c9eea050b Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:48:11 -0800 Subject: netxen: fix ipv6 offload and tx cleanup o fix the ip/tcp hdr offset in tx descriptors for ipv6. o cleanup xmit function, move the tso checks into separate function, this reduces unnecessary endian conversions back and forth. o optimize macros to initialize tx descriptors. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 43 +++++---------- drivers/net/netxen/netxen_nic_hw.c | 4 -- drivers/net/netxen/netxen_nic_main.c | 101 ++++++++++++++++------------------- 3 files changed, 57 insertions(+), 91 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 31311cc66d18..acb2ac971ca3 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -308,27 +308,16 @@ struct netxen_ring_ctx { #define netxen_set_cmd_desc_ctxid(cmd_desc, var) \ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) -#define netxen_set_cmd_desc_flags(cmd_desc, val) \ - (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ - ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f) -#define netxen_set_cmd_desc_opcode(cmd_desc, val) \ - (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ - ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7) - -#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \ - (cmd_desc)->num_of_buffers_total_length = \ - ((cmd_desc)->num_of_buffers_total_length & \ - ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff) -#define netxen_set_cmd_desc_totallength(cmd_desc, val) \ - (cmd_desc)->num_of_buffers_total_length = \ - ((cmd_desc)->num_of_buffers_total_length & \ - ~cpu_to_le32((u32)0xffffff << 8)) | \ - cpu_to_le32(((val) & 0xffffff) << 8) - -#define netxen_get_cmd_desc_opcode(cmd_desc) \ - ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f) -#define netxen_get_cmd_desc_totallength(cmd_desc) \ - ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff) +#define netxen_set_tx_port(_desc, _port) \ + (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0) + +#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \ + (_desc)->flags_opcode = \ + cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)) + +#define netxen_set_tx_frags_len(_desc, _frags, _len) \ + (_desc)->num_of_buffers_total_length = \ + cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)) struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ @@ -757,7 +746,7 @@ extern char netxen_nic_driver_name[]; */ struct netxen_skb_frag { u64 dma; - u32 length; + ulong length; }; #define _netxen_set_bits(config_word, start, bits, val) {\ @@ -783,13 +772,7 @@ struct netxen_skb_frag { struct netxen_cmd_buffer { struct sk_buff *skb; struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; - u32 total_length; - u32 mss; - u16 port; - u8 cmd; - u8 frag_count; - unsigned long time_stamp; - u32 state; + u32 frag_count; }; /* In rx_buffer, we do not need multiple fragments as is a single buffer */ @@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter); void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); -void netxen_tso_check(struct netxen_adapter *adapter, - struct cmd_desc_type0 *desc, struct sk_buff *skb); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index e8a0eed0078e..98d0bcda5f4f 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -508,12 +508,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, cmd_desc = &cmd_desc_arr[i]; pbuf = &adapter->cmd_buf_arr[producer]; - pbuf->mss = 0; - pbuf->total_length = 0; pbuf->skb = NULL; - pbuf->cmd = 0; pbuf->frag_count = 0; - pbuf->port = 0; /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ memcpy(&adapter->ahw.cmd_desc_head[producer], diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index ba01524b5531..cb3912381802 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -39,6 +39,7 @@ #include "netxen_nic_phan_reg.h" #include +#include #include MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); @@ -1137,29 +1138,46 @@ static int netxen_nic_close(struct net_device *netdev) return 0; } -void netxen_tso_check(struct netxen_adapter *adapter, +static bool netxen_tso_check(struct net_device *netdev, struct cmd_desc_type0 *desc, struct sk_buff *skb) { - if (desc->mss) { - desc->total_hdr_length = (sizeof(struct ethhdr) + - ip_hdrlen(skb) + tcp_hdrlen(skb)); + bool tso = false; + u8 opcode = TX_ETHER_PKT; - if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) && - (skb->protocol == htons(ETH_P_IPV6))) - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6); - else - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); + if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + skb_shinfo(skb)->gso_size > 0) { + + desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + desc->total_hdr_length = + skb_transport_offset(skb) + tcp_hdrlen(skb); + + opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + TX_TCP_LSO6 : TX_TCP_LSO; + tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); - else if (ip_hdr(skb)->protocol == IPPROTO_UDP) - netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); - else - return; + u8 l4proto; + + if (skb->protocol == htons(ETH_P_IP)) { + l4proto = ip_hdr(skb)->protocol; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCP_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDP_PKT; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + l4proto = ipv6_hdr(skb)->nexthdr; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCPV6_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDPV6_PKT; + } } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); + netxen_set_tx_flags_opcode(desc, 0, opcode); + return tso; } static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -1167,33 +1185,20 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_hardware_context *hw = &adapter->ahw; unsigned int first_seg_len = skb->len - skb->data_len; + struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; - unsigned int i; + struct cmd_desc_type0 *hwdesc; + int i, k; u32 producer, consumer; - u32 saved_producer = 0; - struct cmd_desc_type0 *hwdesc; - int k; - struct netxen_cmd_buffer *pbuf = NULL; - int frag_count; - int no_of_desc; + int frag_count, no_of_desc; u32 num_txd = adapter->max_tx_desc_count; + bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; - if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { - if (skb_shinfo(skb)->gso_size > 0) { - - no_of_desc++; - if ((ip_hdrlen(skb) + tcp_hdrlen(skb) + - sizeof(struct ethhdr)) > - (sizeof(struct cmd_desc_type0) - 2)) { - no_of_desc++; - } - } - } producer = adapter->cmd_producer; smp_mb(); @@ -1205,34 +1210,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* Copy the descriptors into the hardware */ - saved_producer = producer; hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; - if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && - skb_shinfo(skb)->gso_size > 0) { - pbuf->mss = skb_shinfo(skb)->gso_size; - hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - } else { - pbuf->mss = 0; - hwdesc->mss = 0; - } - pbuf->total_length = skb->len; + + is_tso = netxen_tso_check(netdev, hwdesc, skb); + pbuf->skb = skb; - pbuf->cmd = TX_ETHER_PKT; pbuf->frag_count = frag_count; - pbuf->port = adapter->portnum; buffrag = &pbuf->frag_array[0]; buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); buffrag->length = first_seg_len; - netxen_set_cmd_desc_totallength(hwdesc, skb->len); - netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); - netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT); + netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); + netxen_set_tx_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum); hwdesc->buffer1_length = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); @@ -1285,16 +1278,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } producer = get_next_index(producer, num_txd); - /* might change opcode to TX_TCP_LSO */ - netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); - /* For LSO, we need to copy the MAC/IP/TCP headers into * the descriptor ring */ - if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) - == TX_TCP_LSO) { + if (is_tso) { int hdr_len, first_hdr_len, more_hdr; - hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { first_hdr_len = sizeof(struct cmd_desc_type0) - 2; more_hdr = 1; -- cgit v1.2.3 From c7860a2aec571ea95d3ad19b8d9775b27828baac Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:48:32 -0800 Subject: netxen: fix link speed reporting for some boards o Read negotiated link speed when link state changes. o Fix link speed reporting for hybrid nic boards, which have both 1Gbps and 10Gbps ports. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 3 ++- drivers/net/netxen/netxen_nic_ethtool.c | 31 +++++++++++++++++++++++-------- drivers/net/netxen/netxen_nic_hw.c | 28 ++++++++++++++++++++-------- drivers/net/netxen/netxen_nic_main.c | 14 +++++++++++++- 4 files changed, 58 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index acb2ac971ca3..a674a23f72b4 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -499,7 +499,8 @@ typedef enum { NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a, NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b, NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031, - NETXEN_BRDTYPE_P3_10G_XFP = 0x0032 + NETXEN_BRDTYPE_P3_10G_XFP = 0x0032, + NETXEN_BRDTYPE_P3_10G_TP = 0x0080 } netxen_brdtype_t; diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index e45ce2951729..c0bd40fcf708 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -136,11 +136,9 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->port = PORT_TP; - if (netif_running(dev)) { - ecmd->speed = adapter->link_speed; - ecmd->duplex = adapter->link_duplex; - ecmd->autoneg = adapter->link_autoneg; - } + ecmd->speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex; + ecmd->autoneg = adapter->link_autoneg; } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { u32 val; @@ -171,7 +169,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else return -EIO; - ecmd->phy_address = adapter->portnum; + ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; switch ((netxen_brdtype_t) boardinfo->board_type) { @@ -180,13 +178,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - case NETXEN_BRDTYPE_P3_10000_BASE_T: ecmd->supported |= SUPPORTED_Autoneg; ecmd->advertising |= ADVERTISED_Autoneg; case NETXEN_BRDTYPE_P2_SB31_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4_LP: + case NETXEN_BRDTYPE_P3_10000_BASE_T: ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; @@ -204,16 +202,33 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; break; - case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: case NETXEN_BRDTYPE_P3_10G_SFP_CT: case NETXEN_BRDTYPE_P3_10G_SFP_QT: + ecmd->advertising |= ADVERTISED_TP; + ecmd->supported |= SUPPORTED_TP; + case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_XFP: ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; break; + case NETXEN_BRDTYPE_P3_10G_TP: + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); + ecmd->advertising |= + (ADVERTISED_FIBRE | ADVERTISED_TP); + ecmd->port = PORT_FIBRE; + } else { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); + ecmd->advertising |= + (ADVERTISED_TP | ADVERTISED_Autoneg); + ecmd->port = PORT_TP; + } + break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", (netxen_brdtype_t) boardinfo->board_type); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 98d0bcda5f4f..4276f7f82238 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -2036,7 +2036,13 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) rv = -1; } - DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type); + if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { + u32 gpio = netxen_nic_reg_read(adapter, + NETXEN_ROMUSB_GLB_PAD_GPIO_I); + if ((gpio & 0x8000) == 0) + boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP; + } + switch ((netxen_brdtype_t) boardinfo->board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: adapter->ahw.board_type = NETXEN_NIC_GBE; @@ -2055,7 +2061,6 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_10G_SFP_QT: case NETXEN_BRDTYPE_P3_10G_XFP: case NETXEN_BRDTYPE_P3_10000_BASE_T: - adapter->ahw.board_type = NETXEN_NIC_XGBE; break; case NETXEN_BRDTYPE_P1_BD: @@ -2065,9 +2070,12 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - adapter->ahw.board_type = NETXEN_NIC_GBE; break; + case NETXEN_BRDTYPE_P3_10G_TP: + adapter->ahw.board_type = (adapter->portnum < 2) ? + NETXEN_NIC_XGBE : NETXEN_NIC_GBE; + break; default: printk("%s: Unknown(%x)\n", netxen_nic_driver_name, boardinfo->board_type); @@ -2112,12 +2120,16 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) { __u32 status; __u32 autoneg; - __u32 mode; __u32 port_mode; - netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode); - if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */ + if (!netif_carrier_ok(adapter->netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = -1; + adapter->link_autoneg = AUTONEG_ENABLE; + return; + } + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &port_mode, 4); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -2143,7 +2155,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) adapter->link_speed = SPEED_1000; break; default: - adapter->link_speed = -1; + adapter->link_speed = 0; break; } switch (netxen_get_phy_duplex(status)) { @@ -2166,7 +2178,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) goto link_down; } else { link_down: - adapter->link_speed = -1; + adapter->link_speed = 0; adapter->link_duplex = -1; } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cb3912381802..2c6ce6ffde09 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -243,7 +243,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; case NETXEN_BRDTYPE_P2_SB35_4G: @@ -252,6 +252,14 @@ static void netxen_check_options(struct netxen_adapter *adapter) adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; + case NETXEN_BRDTYPE_P3_10G_TP: + adapter->msix_supported = !!use_msi_x; + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + else + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; + break; + default: adapter->msix_supported = 0; adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; @@ -1396,6 +1404,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1404,6 +1414,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_on(netdev); netif_wake_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } } -- cgit v1.2.3 From 27c915a4d843b90eb4065298969578d15e5e6ab0 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:49:00 -0800 Subject: netxen: firmware init fix o Fix order or rom register writes. o Reduce udelays when writing rom registers. This cuts the firmware init time by 40%. o Do not reset core/memory clocks when reinitializing driver. Firmware willl handle this when initialized. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 6 ++--- drivers/net/netxen/netxen_nic_init.c | 35 ++++++++++++++++----------- drivers/net/netxen/netxen_nic_main.c | 47 +++++++++++++++++++++--------------- 3 files changed, 51 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 4276f7f82238..511db2ac57c9 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -939,7 +939,7 @@ int netxen_load_firmware(struct netxen_adapter *adapter) { int i; u32 data, size = 0; - u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START; + u32 flashaddr = NETXEN_BOOTLD_START; size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; @@ -951,10 +951,8 @@ int netxen_load_firmware(struct netxen_adapter *adapter) if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) return -EIO; - adapter->pci_mem_write(adapter, memaddr, &data, 4); + adapter->pci_mem_write(adapter, flashaddr, &data, 4); flashaddr += 4; - memaddr += 4; - cond_resched(); } msleep(1); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index c0e06a653170..a3203644b482 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -439,6 +439,8 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) long timeout = 0; long done = 0; + cond_resched(); + while (done == 0) { done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS); done &= 2; @@ -533,12 +535,9 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - cond_resched(); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { printk("Error waiting for rom done\n"); @@ -546,7 +545,7 @@ static int do_rom_fast_read(struct netxen_adapter *adapter, } /* reset abyte_cnt and dummy_byte_cnt */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - udelay(100); /* prevent bursting on CRB */ + udelay(10); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); @@ -884,14 +883,16 @@ int netxen_flash_unlock(struct netxen_adapter *adapter) int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) { int addr, val; - int i, init_delay = 0; + int i, n, init_delay = 0; struct crb_addr_pair *buf; - unsigned offset, n; + unsigned offset; u32 off; /* resetall */ + rom_lock(adapter); netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); + netxen_rom_unlock(adapter); if (verbose) { if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0) @@ -910,7 +911,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { if (netxen_rom_fast_read(adapter, 0, &n) != 0 || - (n != 0xcafecafeUL) || + (n != 0xcafecafe) || netxen_rom_fast_read(adapter, 4, &n) != 0) { printk(KERN_ERR "%s: ERROR Reading crb_init area: " "n: %08x\n", netxen_nic_driver_name, n); @@ -975,6 +976,14 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* do not reset PCI */ if (off == (ROMUSB_GLB + 0xbc)) continue; + if (off == (ROMUSB_GLB + 0xa8)) + continue; + if (off == (ROMUSB_GLB + 0xc8)) /* core clock */ + continue; + if (off == (ROMUSB_GLB + 0x24)) /* MN clock */ + continue; + if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */ + continue; if (off == (NETXEN_CRB_PEG_NET_1 + 0x18)) buf[i].data = 0x1020; /* skip the function enable register */ @@ -992,23 +1001,21 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) continue; } + init_delay = 1; /* After writing this register, HW needs time for CRB */ /* to quiet down (else crb_window returns 0xffffffff) */ if (off == NETXEN_ROMUSB_GLB_SW_RESET) { - init_delay = 1; + init_delay = 1000; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { /* hold xdma in reset also */ buf[i].data = NETXEN_NIC_XDMA_RESET; + buf[i].data = 0x8000ff; } } adapter->hw_write_wx(adapter, off, &buf[i].data, 4); - if (init_delay == 1) { - msleep(1000); - init_delay = 0; - } - msleep(1); + msleep(init_delay); } kfree(buf); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2c6ce6ffde09..cbe2b3e814dd 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -280,10 +280,15 @@ static void netxen_check_options(struct netxen_adapter *adapter) static int netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) { - int ret = 0; + u32 val, timeout; if (first_boot == 0x55555555) { /* This is the first boot after power up */ + adapter->pci_write_normalize(adapter, + NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; /* PCI bus master workaround */ adapter->hw_read_wx(adapter, @@ -303,18 +308,26 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) /* clear the register for future unloads/loads */ adapter->pci_write_normalize(adapter, NETXEN_CAM_RAM(0x1fc), 0); - ret = -1; + return -EIO; } - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - /* Start P2 boot loader */ - adapter->pci_write_normalize(adapter, - NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } + /* Start P2 boot loader */ + val = adapter->pci_read_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE); + adapter->pci_write_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); + timeout = 0; + do { + msleep(1); + val = adapter->pci_read_normalize(adapter, + NETXEN_CAM_RAM(0x1fc)); + + if (++timeout > 5000) + return -EIO; + + } while (val == NETXEN_BDINFO_MAGIC); } - return ret; + return 0; } static void netxen_set_port_mode(struct netxen_adapter *adapter) @@ -793,8 +806,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); - netxen_load_firmware(adapter); } + netxen_load_firmware(adapter); if (NX_IS_REVISION_P3(revision_id)) netxen_pcie_strap_init(adapter); @@ -810,13 +823,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } - if ((first_boot == 0x55555555) && - (NX_IS_REVISION_P2(revision_id))) { - /* Unlock the HW, prompting the boot sequence */ - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } - err = netxen_initialize_adapter_offload(adapter); if (err) goto err_out_iounmap; @@ -830,7 +836,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i); /* Handshake with the card before we register the devices. */ - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + if (err) + goto err_out_free_offload; } /* first_driver */ @@ -934,6 +942,7 @@ err_out_disable_msi: if (adapter->flags & NETXEN_NIC_MSI_ENABLED) pci_disable_msi(pdev); +err_out_free_offload: if (first_driver) netxen_free_adapter_offload(adapter); -- cgit v1.2.3 From 06e9d9f9783860fe4c602ef491f47211804ccc96 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:49:22 -0800 Subject: netxen: cleanup mac list on driver unload This fixes a tiny memory leak when driver is unloaded. The mac address list maintained in netxen_adapter needs to deleted when driver is going down. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 + drivers/net/netxen/netxen_nic_hw.c | 13 +++++++++++++ drivers/net/netxen/netxen_nic_main.c | 3 +++ 3 files changed, 17 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index a674a23f72b4..6598a34b87d4 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1478,6 +1478,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter); u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); +void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 511db2ac57c9..e2d2a2fdbe19 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -627,6 +627,19 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) (struct cmd_desc_type0 *)&req, 1); } +void netxen_p3_free_mac_list(struct netxen_adapter *adapter) +{ + nx_mac_list_t *cur, *next; + + cur = adapter->mac_list; + + while (cur) { + next = cur->next; + kfree(cur); + cur = next; + } +} + #define NETXEN_CONFIG_INTR_COALESCE 3 /* diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cbe2b3e814dd..9268fd2fbacf 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -986,6 +986,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_free_sw_resources(adapter); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_p3_free_mac_list(adapter); } if (adapter->portnum == 0) -- cgit v1.2.3 From 03e678ee968ae54b79c1580c2935895bd863ad95 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:49:43 -0800 Subject: netxen: hold tx lock while sending firmware commands Some firmware commands like mac address addition/deletion are sent on the transmit ring. So need to hold the tx lock before touching tx producer/consumer indices. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index e2d2a2fdbe19..821cff68b3f3 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -503,6 +503,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, i = 0; + netif_tx_lock_bh(adapter->netdev); + producer = adapter->cmd_producer; do { cmd_desc = &cmd_desc_arr[i]; @@ -527,6 +529,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netif_tx_unlock_bh(adapter->netdev); + return 0; } -- cgit v1.2.3 From 6f70340698333f14b1d9c9e913c5de8f66b72c55 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:50:00 -0800 Subject: netxen: handle dma mapping failures o Bail out if pci_map_single() fails while replenishing rx ring. o Drop packet if pci_map_{single,page}() fail in tx. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_init.c | 68 +++++++++++++++++------------------- drivers/net/netxen/netxen_nic_main.c | 38 ++++++++++++++++++-- 3 files changed, 67 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 6598a34b87d4..c11c568fd7db 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -860,7 +860,6 @@ struct nx_host_rds_ring { u32 skb_size; struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ struct list_head free_list; - int begin_alloc; }; /* diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index a3203644b482..ca7c8d8050c9 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) } memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); INIT_LIST_HEAD(&rds_ring->free_list); - rds_ring->begin_alloc = 0; /* * Now go through all of them, set reference handles * and put them in the queues. @@ -1435,7 +1434,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; int count = 0; - int index = 0; netxen_ctx_msg msg = 0; dma_addr_t dma; struct list_head *head; @@ -1443,7 +1441,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; - index = rds_ring->begin_alloc; head = &rds_ring->free_list; /* We can start writing rx descriptors into the phantom memory. */ @@ -1451,39 +1448,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) skb = dev_alloc_skb(rds_ring->skb_size); if (unlikely(!skb)) { - rds_ring->begin_alloc = index; break; } + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + break; + } + + count++; buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - count++; /* now there should be no failure */ - pdesc = &rds_ring->desc_head[producer]; - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); - /* This will be setup when we receive the - * buffer after it has been filled FSL TBD TBD - * skb->dev = netdev; - */ - dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, - PCI_DMA_FROMDEVICE); - pdesc->addr_buffer = cpu_to_le64(dma); buffer->skb = skb; buffer->state = NETXEN_BUFFER_BUSY; buffer->dma = dma; + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->addr_buffer = cpu_to_le64(dma); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - DPRINTK(INFO, "done writing descripter\n"); - producer = - get_next_index(producer, rds_ring->max_rx_desc_count); - index = get_next_index(index, rds_ring->max_rx_desc_count); + + producer = get_next_index(producer, rds_ring->max_rx_desc_count); } /* if we did allocate buffers, then write the count to Phantom */ if (count) { - rds_ring->begin_alloc = index; rds_ring->producer = producer; /* Window = 1 */ adapter->pci_write_normalize(adapter, @@ -1522,49 +1517,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; int count = 0; - int index = 0; struct list_head *head; + dma_addr_t dma; rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; - index = rds_ring->begin_alloc; head = &rds_ring->free_list; /* We can start writing rx descriptors into the phantom memory. */ while (!list_empty(head)) { skb = dev_alloc_skb(rds_ring->skb_size); if (unlikely(!skb)) { - rds_ring->begin_alloc = index; break; } + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + break; + } + + count++; buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - count++; /* now there should be no failure */ - pdesc = &rds_ring->desc_head[producer]; - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); buffer->skb = skb; buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, - PCI_DMA_FROMDEVICE); + buffer->dma = dma; /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->addr_buffer = cpu_to_le64(buffer->dma); - producer = - get_next_index(producer, rds_ring->max_rx_desc_count); - index = get_next_index(index, rds_ring->max_rx_desc_count); - buffer = &rds_ring->rx_buf_arr[index]; + + producer = get_next_index(producer, rds_ring->max_rx_desc_count); } /* if we did allocate buffers, then write the count to Phantom */ if (count) { - rds_ring->begin_alloc = index; rds_ring->producer = producer; /* Window = 1 */ adapter->pci_write_normalize(adapter, diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9268fd2fbacf..86867405a367 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1200,6 +1200,24 @@ static bool netxen_tso_check(struct net_device *netdev, return tso; } +static void +netxen_clean_tx_dma_mapping(struct pci_dev *pdev, + struct netxen_cmd_buffer *pbuf, int last) +{ + int k; + struct netxen_skb_frag *buffrag; + + buffrag = &pbuf->frag_array[0]; + pci_unmap_single(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + + for (k = 1; k < last; k++) { + buffrag = &pbuf->frag_array[k]; + pci_unmap_page(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + } +} + static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -1208,6 +1226,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; struct cmd_desc_type0 *hwdesc; + struct pci_dev *pdev = adapter->pdev; + dma_addr_t temp_dma; int i, k; u32 producer, consumer; @@ -1240,8 +1260,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pbuf->skb = skb; pbuf->frag_count = frag_count; buffrag = &pbuf->frag_array[0]; - buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, + temp_dma = pci_map_single(pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) + goto drop_packet; + + buffrag->dma = temp_dma; buffrag->length = first_seg_len; netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_port(hwdesc, adapter->portnum); @@ -1253,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct skb_frag_struct *frag; int len, temp_len; unsigned long offset; - dma_addr_t temp_dma; /* move to next desc. if there is a need */ if ((i & 0x3) == 0) { @@ -1269,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) offset = frag->page_offset; temp_len = len; - temp_dma = pci_map_page(adapter->pdev, frag->page, offset, + temp_dma = pci_map_page(pdev, frag->page, offset, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) { + netxen_clean_tx_dma_mapping(pdev, pbuf, i); + goto drop_packet; + } buffrag++; buffrag->dma = temp_dma; @@ -1345,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; return NETDEV_TX_OK; + +drop_packet: + adapter->stats.txdropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } static int netxen_nic_check_temp(struct netxen_adapter *adapter) -- cgit v1.2.3 From 2950e952920811be465ec95c6b56f03dc66a05c0 Mon Sep 17 00:00:00 2001 From: Jos-Vicente Gilabert Date: Wed, 14 Jan 2009 20:55:00 -0800 Subject: drivers/net/irda/irda-usb.c: fix buffer overflow Taken from http://bugzilla.kernel.org/show_bug.cgi?id=12397 We're doing an sprintf of an 11-char string into an 11-char buffer. Whoops. It breaks firmware uploading. Reported-by: Jos-Vicente Gilabert Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/irda/irda-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 29118f58a141..3a22dc41b656 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1073,7 +1073,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) { unsigned int i; int ret; - char stir421x_fw_name[11]; + char stir421x_fw_name[12]; const struct firmware *fw; const unsigned char *fw_version_ptr; /* pointer to version string */ unsigned long fw_version = 0; -- cgit v1.2.3 From 937f1ba56b4be37d9e2ad77412f95048662058d2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 14 Jan 2009 21:05:05 -0800 Subject: net: Add init_dummy_netdev() and fix EMAC driver using it This adds an init_dummy_netdev() function that gets a network device structure (allocation and lifetime entirely under caller's control) and initialize the minimum amount of fields so it can be used to schedule NAPI polls without registering a full blown interface. This is to be used by drivers that need to tie several hardware interfaces to a single NAPI poll scheduler due to HW limitations. It also updates the ibm_newemac driver to use that, this fixing the oops on 2.6.29 due to passing NULL as "dev" to netif_napi_add() Symbol is exported GPL only a I don't think we want binary drivers doing that sort of acrobatics (if we want them at all). Signed-off-by: Benjamin Herrenschmidt Tested-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/mal.c | 4 +++- drivers/net/ibm_newemac/mal.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index ecf9798987fa..2a2fc17b2878 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev, INIT_LIST_HEAD(&mal->list); spin_lock_init(&mal->lock); - netif_napi_add(NULL, &mal->napi, mal_poll, + init_dummy_netdev(&mal->dummy_dev); + + netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll, CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); /* Load power-on reset defaults */ diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 2f0a87360844..9ededfbf0726 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -214,6 +214,8 @@ struct mal_instance { int index; spinlock_t lock; + struct net_device dummy_dev; + unsigned int features; }; -- cgit v1.2.3 From d57bc36e7aba9e3a00d154f5eff80ff596146fc4 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 14 Jan 2009 21:05:55 -0800 Subject: ax88796: start_xmit fix using net_device_ops This patch hooks up the start_xmit/tx_timeout/get_stats callbacks in the ax88796 driver since they no longer are installed by the lib8390 code. Without this patch the function dev_hard_start_xmit() crashes due to a start_xmit callback with the value NULL. While at it, update the ax88796 driver to make use of use of struct net_device_ops. Signed-off-by: Magnus Damm Signed-off-by: David S. Miller --- drivers/net/ax88796.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 337488ec707c..a4eb6c40678c 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -37,7 +37,10 @@ static int phy_debug = 0; #define __ei_open ax_ei_open #define __ei_close ax_ei_close #define __ei_poll ax_ei_poll +#define __ei_start_xmit ax_ei_start_xmit #define __ei_tx_timeout ax_ei_tx_timeout +#define __ei_get_stats ax_ei_get_stats +#define __ei_set_multicast_list ax_ei_set_multicast_list #define __ei_interrupt ax_ei_interrupt #define ____alloc_ei_netdev ax__alloc_ei_netdev #define __NS8390_init ax_NS8390_init @@ -623,6 +626,23 @@ static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom) } #endif +static const struct net_device_ops ax_netdev_ops = { + .ndo_open = ax_open, + .ndo_stop = ax_close, + .ndo_do_ioctl = ax_ioctl, + + .ndo_start_xmit = ax_ei_start_xmit, + .ndo_tx_timeout = ax_ei_tx_timeout, + .ndo_get_stats = ax_ei_get_stats, + .ndo_set_multicast_list = ax_ei_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ax_ei_poll, +#endif +}; + /* setup code */ static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) @@ -738,9 +758,7 @@ static int ax_init_dev(struct net_device *dev, int first_init) ei_status.get_8390_hdr = &ax_get_8390_hdr; ei_status.priv = 0; - dev->open = ax_open; - dev->stop = ax_close; - dev->do_ioctl = ax_ioctl; + dev->netdev_ops = &ax_netdev_ops; dev->ethtool_ops = &ax_ethtool_ops; ax->msg_enable = NETIF_MSG_LINK; @@ -753,9 +771,6 @@ static int ax_init_dev(struct net_device *dev, int first_init) ax->mii.mdio_write = ax_phy_write; ax->mii.dev = dev; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ax_ei_poll; -#endif ax_NS8390_init(dev, 0); if (first_init) -- cgit v1.2.3 From 1cf167f27ad2720af11ee8aa350009342f909e70 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:22:18 -0800 Subject: bnx2x: Using singlethread work queue Since slow-path events, including link update, are handled in work-queue, a race condition was introduced in the self-test that sometimes caused the link status to fail: the self-test was running under RTNL lock, and if the link-watch was scheduled it stoped the shared work-queue (waiting for the RTNL lock) and so the link update event was not handled until the self-test ended (releasing the RTNL lock) with failure (since the link status was not updated) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_main.c | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index fd705d1295a7..96a8889afbe1 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -811,7 +811,7 @@ struct bnx2x { int pm_cap; int pcie_cap; - struct work_struct sp_task; + struct delayed_work sp_task; struct work_struct reset_task; struct timer_list timer; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4be05847f86f..cc6ffba74592 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -95,6 +95,7 @@ MODULE_PARM_DESC(debug, "default debug msglevel"); module_param(use_multi, int, 0); MODULE_PARM_DESC(use_multi, "use per-CPU queues"); #endif +static struct workqueue_struct *bnx2x_wq; enum bnx2x_board_type { BCM57710 = 0, @@ -671,7 +672,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) synchronize_irq(bp->pdev->irq); /* make sure sp_task is not running */ - cancel_work_sync(&bp->sp_task); + cancel_delayed_work(&bp->sp_task); + flush_workqueue(bnx2x_wq); } /* fast path */ @@ -1660,7 +1662,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) if (unlikely(status & 0x1)) { - schedule_work(&bp->sp_task); + queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); status &= ~0x1; if (!status) @@ -2820,7 +2822,7 @@ static void bnx2x_attn_int(struct bnx2x *bp) static void bnx2x_sp_task(struct work_struct *work) { - struct bnx2x *bp = container_of(work, struct bnx2x, sp_task); + struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work); u16 status; @@ -2875,7 +2877,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) return IRQ_HANDLED; #endif - schedule_work(&bp->sp_task); + queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); return IRQ_HANDLED; } @@ -7501,7 +7503,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) mutex_init(&bp->port.phy_mutex); - INIT_WORK(&bp->sp_task, bnx2x_sp_task); + INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_WORK(&bp->reset_task, bnx2x_reset_task); rc = bnx2x_get_hwinfo(bp); @@ -10519,12 +10521,20 @@ static struct pci_driver bnx2x_pci_driver = { static int __init bnx2x_init(void) { + bnx2x_wq = create_singlethread_workqueue("bnx2x"); + if (bnx2x_wq == NULL) { + printk(KERN_ERR PFX "Cannot create workqueue\n"); + return -ENOMEM; + } + return pci_register_driver(&bnx2x_pci_driver); } static void __exit bnx2x_cleanup(void) { pci_unregister_driver(&bnx2x_pci_driver); + + destroy_workqueue(bnx2x_wq); } module_init(bnx2x_init); -- cgit v1.2.3 From 58f4c4cfce5c4715b79621f0a635925c55f855d5 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:23:36 -0800 Subject: bnx2x: Missing memory barriers While working on IA64, it became clear that the following memory barriers are missing Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index cc6ffba74592..f0b2e73b87f7 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1357,11 +1357,23 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp, rx_prods.cqe_prod = rx_comp_prod; rx_prods.sge_prod = rx_sge_prod; + /* + * Make sure that the BD and SGE data is updated before updating the + * producers since FW might read the BD/SGE right after the producer + * is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes BDs must have buffers. + */ + wmb(); + for (i = 0; i < sizeof(struct tstorm_eth_rx_producers)/4; i++) REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)) + i*4, ((u32 *)&rx_prods)[i]); + mmiowb(); /* keep prod updates ordered */ + DP(NETIF_MSG_RX_STATUS, "Wrote: bd_prod %u cqe_prod %u sge_prod %u\n", bd_prod, rx_comp_prod, rx_sge_prod); @@ -1582,7 +1594,6 @@ next_cqe: /* Update producers */ bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod, fp->rx_sge_prod); - mmiowb(); /* keep prod updates ordered */ fp->rx_pkt += rx_pkt; fp->rx_calls++; @@ -8729,6 +8740,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) tx_bd->general_data = ((UNICAST_ADDRESS << ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1); + wmb(); + fp->hw_tx_prods->bds_prod = cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + 1); mb(); /* FW restriction: must not reorder writing nbd and packets */ @@ -8780,7 +8793,6 @@ test_loopback_rx_exit: /* Update producers */ bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, fp->rx_sge_prod); - mmiowb(); /* keep prod updates ordered */ test_loopback_exit: bp->link_params.loopback_mode = LOOPBACK_NONE; @@ -9707,6 +9719,15 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + /* + * Make sure that the BD data is updated before updating the producer + * since FW might read the BD right after the producer is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes packets must have BDs. + */ + wmb(); + fp->hw_tx_prods->bds_prod = cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd); mb(); /* FW restriction: must not reorder writing nbd and packets */ @@ -9720,6 +9741,9 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { + /* We want bnx2x_tx_int to "see" the updated tx_bd_prod + if we put Tx into XOFF state. */ + smp_mb(); netif_stop_queue(dev); bp->eth_stats.driver_xoff++; if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) -- cgit v1.2.3 From 4f40f2cba244e04c0f385c5ce60498b513b335dd Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:24:17 -0800 Subject: bnx2x: Using system page size for SGE When the page size is not 4KB, the FW must be programmed to work with the right SGE boundaries and fragment list length. To avoid confusion with the BCM_PAGE_SIZE which is set to 4KB for the FW sake, another alias for the system page size was added to explicitly indicate that it is meant for the SGE Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 3 +++ drivers/net/bnx2x_main.c | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 96a8889afbe1..2cd1e4278283 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -150,6 +150,9 @@ struct sw_rx_page { #define PAGES_PER_SGE_SHIFT 0 #define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT) +#define SGE_PAGE_SIZE PAGE_SIZE +#define SGE_PAGE_SHIFT PAGE_SHIFT +#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr) #define BCM_RX_ETH_PAYLOAD_ALIGN 64 diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f0b2e73b87f7..75b2624cd60b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -974,7 +974,7 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp, return; pci_unmap_page(bp->pdev, pci_unmap_addr(sw_buf, mapping), - BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); + SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); __free_pages(page, PAGES_PER_SGE_SHIFT); sw_buf->page = NULL; @@ -1002,7 +1002,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp, if (unlikely(page == NULL)) return -ENOMEM; - mapping = pci_map_page(bp->pdev, page, 0, BCM_PAGE_SIZE*PAGES_PER_SGE, + mapping = pci_map_page(bp->pdev, page, 0, SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { __free_pages(page, PAGES_PER_SGE_SHIFT); @@ -1098,9 +1098,9 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, struct eth_fast_path_rx_cqe *fp_cqe) { struct bnx2x *bp = fp->bp; - u16 sge_len = BCM_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - + u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - le16_to_cpu(fp_cqe->len_on_bd)) >> - BCM_PAGE_SHIFT; + SGE_PAGE_SHIFT; u16 last_max, last_elem, first_elem; u16 delta = 0; u16 i; @@ -1205,22 +1205,22 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, u16 cqe_idx) { struct sw_rx_page *rx_pg, old_rx_pg; - struct page *sge; u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd); u32 i, frag_len, frag_size, pages; int err; int j; frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd; - pages = BCM_PAGE_ALIGN(frag_size) >> BCM_PAGE_SHIFT; + pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT; /* This is needed in order to enable forwarding support */ if (frag_size) - skb_shinfo(skb)->gso_size = min((u32)BCM_PAGE_SIZE, + skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE, max(frag_size, (u32)len_on_bd)); #ifdef BNX2X_STOP_ON_ERROR - if (pages > 8*PAGES_PER_SGE) { + if (pages > + min((u32)8, (u32)MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE) { BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n", pages, cqe_idx); BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n", @@ -1236,9 +1236,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* FW gives the indices of the SGE as if the ring is an array (meaning that "next" element will consume 2 indices) */ - frag_len = min(frag_size, (u32)(BCM_PAGE_SIZE*PAGES_PER_SGE)); + frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE)); rx_pg = &fp->rx_page_ring[sge_idx]; - sge = rx_pg->page; old_rx_pg = *rx_pg; /* If we fail to allocate a substitute page, we simply stop @@ -1251,7 +1250,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* Unmap the page as we r going to pass it to the stack */ pci_unmap_page(bp->pdev, pci_unmap_addr(&old_rx_pg, mapping), - BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); + SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); /* Add one frag and update the appropriate fields in the skb */ skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len); @@ -4544,7 +4543,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp) if (bp->flags & TPA_ENABLE_FLAG) { tstorm_client.max_sges_for_packet = - BCM_PAGE_ALIGN(tstorm_client.mtu) >> BCM_PAGE_SHIFT; + SGE_PAGE_ALIGN(tstorm_client.mtu) >> SGE_PAGE_SHIFT; tstorm_client.max_sges_for_packet = ((tstorm_client.max_sges_for_packet + PAGES_PER_SGE - 1) & (~(PAGES_PER_SGE - 1))) >> @@ -4727,10 +4726,11 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) bp->e1hov); } - /* Init CQ ring mapping and aggregation size */ - max_agg_size = min((u32)(bp->rx_buf_size + - 8*BCM_PAGE_SIZE*PAGES_PER_SGE), - (u32)0xffff); + /* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */ + max_agg_size = + min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) * + SGE_PAGE_SIZE * PAGES_PER_SGE), + (u32)0xffff); for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; -- cgit v1.2.3 From ad33ea3a8d2ec324dc0f46b6ae404d824d2b349b Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:24:57 -0800 Subject: bnx2x: Missing mask when calculating flow control Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 75b2624cd60b..9b1555820f52 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1899,7 +1899,8 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) static void bnx2x_calc_fc_adv(struct bnx2x *bp) { - switch (bp->link_vars.ieee_fc) { + switch (bp->link_vars.ieee_fc & + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: bp->port.advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause); -- cgit v1.2.3 From 3c96c68b0c67d11b8519bc38233aec586f0211f4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:25:31 -0800 Subject: bnx2x: Flow control updated before reporting the link Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 9b1555820f52..4f1ee1f2968c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1970,10 +1970,11 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp) rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); bnx2x_release_phy_lock(bp); + bnx2x_calc_fc_adv(bp); + if (bp->link_vars.link_up) bnx2x_link_report(bp); - bnx2x_calc_fc_adv(bp); return rc; } -- cgit v1.2.3 From a5e9a7cfad5fd301ce2b7869bbf386b70aa39e7c Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:26:01 -0800 Subject: bnx2x: Protecting the link change indication Without this lock, in some race conditions the driver missed link change indication Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4f1ee1f2968c..701bcc1260c2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2234,9 +2234,7 @@ static void bnx2x_link_attn(struct bnx2x *bp) /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bnx2x_acquire_phy_lock(bp); bnx2x_link_update(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); if (bp->link_vars.link_up) { @@ -2485,6 +2483,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) if (asserted & ATTN_HARD_WIRED_MASK) { if (asserted & ATTN_NIG_FOR_FUNC) { + bnx2x_acquire_phy_lock(bp); + /* save nig interrupt mask */ bp->nig_mask = REG_RD(bp, nig_int_mask_addr); REG_WR(bp, nig_int_mask_addr, 0); @@ -2540,8 +2540,10 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) REG_WR(bp, hc_addr, asserted); /* now set back the mask */ - if (asserted & ATTN_NIG_FOR_FUNC) + if (asserted & ATTN_NIG_FOR_FUNC) { REG_WR(bp, nig_int_mask_addr, bp->nig_mask); + bnx2x_release_phy_lock(bp); + } } static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) -- cgit v1.2.3 From 0c6671b0d94f706dfc20cb22d792218ba9814412 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:26:51 -0800 Subject: bnx2x: VLAN tagged packets without VLAN offload Wrong handling of tagged packet if VLAN offload is disabled caused packets to get corrupted Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 12 +++++++----- drivers/net/bnx2x_main.c | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 2cd1e4278283..e7fbca7722dc 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -20,6 +20,11 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#define BCM_VLAN 1 +#endif + + /* error/debug prints */ #define DRV_MODULE_NAME "bnx2x" @@ -78,11 +83,6 @@ #endif -#ifdef NETIF_F_HW_VLAN_TX -#define BCM_VLAN 1 -#endif - - #define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff) #define U64_HI(x) (u32)(((u64)(x)) >> 32) #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) @@ -804,6 +804,8 @@ struct bnx2x { #define TPA_ENABLE_FLAG 0x80 #define NO_MCP_FLAG 0x100 #define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG) +#define HW_VLAN_TX_FLAG 0x400 +#define HW_VLAN_RX_FLAG 0x800 int func; #define BP_PORT(bp) (bp->func % PORT_MAX) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 701bcc1260c2..ca8b25126b22 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -38,9 +38,7 @@ #include #include #include -#ifdef NETIF_F_HW_VLAN_TX - #include -#endif +#include #include #include #include @@ -1283,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, if (likely(new_skb)) { /* fix ip xsum and give it to the stack */ /* (no need to map the new skb) */ +#ifdef BCM_VLAN + int is_vlan_cqe = + (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & + PARSING_FLAGS_VLAN); + int is_not_hwaccel_vlan_cqe = + (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); +#endif prefetch(skb); prefetch(((char *)(skb)) + 128); @@ -1307,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct iphdr *iph; iph = (struct iphdr *)skb->data; +#ifdef BCM_VLAN + /* If there is no Rx VLAN offloading - + take VLAN tag into an account */ + if (unlikely(is_not_hwaccel_vlan_cqe)) + iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); +#endif iph->check = 0; iph->check = ip_fast_csum((u8 *)iph, iph->ihl); } @@ -1314,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, if (!bnx2x_fill_frag_skb(bp, fp, skb, &cqe->fast_path_cqe, cqe_idx)) { #ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN)) + if ((bp->vlgrp != NULL) && is_vlan_cqe && + (!is_not_hwaccel_vlan_cqe)) vlan_hwaccel_receive_skb(skb, bp->vlgrp, le16_to_cpu(cqe->fast_path_cqe. vlan_tag)); @@ -1560,7 +1570,7 @@ reuse_rx: } #ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && + if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & PARSING_FLAGS_VLAN)) vlan_hwaccel_receive_skb(skb, bp->vlgrp, @@ -4538,7 +4548,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp) tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; #ifdef BCM_VLAN - if (bp->rx_mode && bp->vlgrp) { + if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) { tstorm_client.config_flags |= TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE; DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); @@ -9567,11 +9577,14 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) "sending pkt %u @%p next_idx %u bd %u @%p\n", pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd); - if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) { +#ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && + (bp->flags & HW_VLAN_TX_FLAG)) { tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb)); tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG; vlan_off += 4; } else +#endif tx_bd->vlan = cpu_to_le16(pkt_prod); if (xmit_type) { @@ -10017,6 +10030,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); bp->vlgrp = vlgrp; + + /* Set flags according to the required capabilities */ + bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); + + if (dev->features & NETIF_F_HW_VLAN_TX) + bp->flags |= HW_VLAN_TX_FLAG; + + if (dev->features & NETIF_F_HW_VLAN_RX) + bp->flags |= HW_VLAN_RX_FLAG; + if (netif_running(dev)) bnx2x_set_client_config(bp); } @@ -10173,6 +10196,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->features |= NETIF_F_HIGHDMA; #ifdef BCM_VLAN dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); + bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); #endif dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); dev->features |= NETIF_F_TSO6; -- cgit v1.2.3 From 68d5948436c2f782ebb5ddf25a6588ee452e8c30 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:27:36 -0800 Subject: bnx2x: Endianness issues Adding missing le_to_cpu and disabling wrong HW endianity flag (the two complete each other) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ca8b25126b22..d2350dd300b2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1438,7 +1438,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x" " queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags), cqe_fp_flags, cqe->fast_path_cqe.status_flags, - cqe->fast_path_cqe.rss_hash_result, + le32_to_cpu(cqe->fast_path_cqe.rss_hash_result), le16_to_cpu(cqe->fast_path_cqe.vlan_tag), le16_to_cpu(cqe->fast_path_cqe.pkt_len)); @@ -2821,8 +2821,10 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) static void bnx2x_attn_int(struct bnx2x *bp) { /* read local copy of bits */ - u32 attn_bits = bp->def_status_blk->atten_status_block.attn_bits; - u32 attn_ack = bp->def_status_blk->atten_status_block.attn_bits_ack; + u32 attn_bits = le32_to_cpu(bp->def_status_blk->atten_status_block. + attn_bits); + u32 attn_ack = le32_to_cpu(bp->def_status_blk->atten_status_block. + attn_bits_ack); u32 attn_state = bp->attn_state; /* look for changed bits */ @@ -2870,7 +2872,7 @@ static void bnx2x_sp_task(struct work_struct *work) if (status & 0x2) bp->stats_pending = 0; - bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx, + bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx), IGU_INT_NOP, 1); bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx), IGU_INT_NOP, 1); @@ -5161,7 +5163,6 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1); REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1); REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1); - REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1); /* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */ REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1); -- cgit v1.2.3 From a5f67a04d998b0b6e4beb1de8f1247dd93ac1ff4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:28:13 -0800 Subject: bnx2x: Fixing the doorbell size The size of the doorbell is 4KB, this bug become visible when using more than 8 queues Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index e7fbca7722dc..6fcccef4cf3d 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -739,7 +739,7 @@ struct bnx2x { struct bnx2x_fastpath fp[MAX_CONTEXT]; void __iomem *regview; void __iomem *doorbells; -#define BNX2X_DB_SIZE (16*2048) +#define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE) struct net_device *dev; struct pci_dev *pdev; -- cgit v1.2.3 From f5ba6772f226be0266f95642c8162493246d3b79 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:29:18 -0800 Subject: bnx2x: Missing brackets Calculation bug due to missing brackets Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d2350dd300b2..a755fea996d5 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2920,7 +2920,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) #define ADD_64(s_hi, a_hi, s_lo, a_lo) \ do { \ s_lo += a_lo; \ - s_hi += a_hi + (s_lo < a_lo) ? 1 : 0; \ + s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \ } while (0) /* difference = minuend - subtrahend */ -- cgit v1.2.3 From 26c8fa4d8a08b6e7a61f23339e2236218957ecc0 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:29:55 -0800 Subject: bnx2x: Indirection table initialization index Wrong initialization of the multi-queue indirection table - it should be using the function and not the port index Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index a755fea996d5..9e6aa8a1ee91 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4524,7 +4524,7 @@ static void bnx2x_init_context(struct bnx2x *bp) static void bnx2x_init_ind_table(struct bnx2x *bp) { - int port = BP_PORT(bp); + int func = BP_FUNC(bp); int i; if (!is_multi(bp)) @@ -4533,10 +4533,8 @@ static void bnx2x_init_ind_table(struct bnx2x *bp) DP(NETIF_MSG_IFUP, "Initializing indirection table\n"); for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) REG_WR8(bp, BAR_TSTRORM_INTMEM + - TSTORM_INDIRECTION_TABLE_OFFSET(port) + i, - i % bp->num_queues); - - REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); + TSTORM_INDIRECTION_TABLE_OFFSET(func) + i, + BP_CL_ID(bp) + (i % bp->num_queues)); } static void bnx2x_set_client_config(struct bnx2x *bp) @@ -5240,6 +5238,7 @@ static int bnx2x_init_common(struct bnx2x *bp) } bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); if (CHIP_IS_E1H(bp)) -- cgit v1.2.3 From e7799c5f79072b5b34cf08170f142bcb8569cfff Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:30:27 -0800 Subject: bnx2x: MTU Filter Too big packets could pass due to wrong filter size Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 9e6aa8a1ee91..b573951600de 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4543,7 +4543,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp) int port = BP_PORT(bp); int i; - tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD; + tstorm_client.mtu = bp->dev->mtu; tstorm_client.statistics_counter_id = BP_CL_ID(bp); tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; -- cgit v1.2.3 From 0ef00459a638ae4f5d1e5326d3e50232fa80119f Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 21:31:08 -0800 Subject: bnx2x: First slow path interrupt race The "read for interrupts" flag must be set before enabling slow-path interrupts as well (and not just before fast-path interrupts) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index b573951600de..7c533797c064 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4812,6 +4812,15 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) bnx2x_init_context(bp); bnx2x_init_internal(bp, load_code); bnx2x_init_ind_table(bp); + bnx2x_stats_init(bp); + + /* At this point, we are ready for interrupts */ + atomic_set(&bp->intr_sem, 0); + + /* flush all before enabling interrupts */ + mb(); + mmiowb(); + bnx2x_int_enable(bp); } @@ -6420,17 +6429,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } } - bnx2x_stats_init(bp); - bp->state = BNX2X_STATE_OPENING_WAIT4_PORT; - /* Enable Rx interrupt handling before sending the ramrod - as it's completed on Rx FP queue */ - bnx2x_napi_enable(bp); - - /* Enable interrupt handling */ - atomic_set(&bp->intr_sem, 0); - rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); -- cgit v1.2.3 From b96ecfa689126d1e652ebd758da0b5b9b27dbd12 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:46:51 -0800 Subject: korina: fix usage of driver_data Using platform_set_drvdata() here makes no sense, since the driver_data field has already been filled with valuable data (i.e. the MAC address). Also having driver_data point to the net_device is rather pointless since struct korina_device contains an apropriate field for it. Signed-off-by: Phil Sutter Signed-off-by: David S. Miller --- drivers/net/korina.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 4a5580c1126a..fefb33db79a3 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -1089,7 +1089,6 @@ static int korina_probe(struct platform_device *pdev) return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); - platform_set_drvdata(pdev, dev); lp = netdev_priv(dev); bif->dev = dev; -- cgit v1.2.3 From a13b27826a67bfc0ca444fb42885f2069b6898e2 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:47:50 -0800 Subject: korina: reset resource buffer size to 1536 The new value is the one used in the external patch before and allows at least a standard MTU of 1500 to be handled correctly. Impact of this change gets visible when bigger packets are to be received, issuing: | ping -s 492 and bigger payload sized led to 100% packet loss. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli --- drivers/net/korina.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index fefb33db79a3..e30c2f437d19 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -84,7 +84,10 @@ #define KORINA_NUM_RDS 64 /* number of receive descriptors */ #define KORINA_NUM_TDS 64 /* number of transmit descriptors */ -#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */ +/* KORINA_RBSIZE is the hardware's default maximum receive + * frame size in bytes. Having this hardcoded means that there + * is no support for MTU sizes greater than 1500. */ +#define KORINA_RBSIZE 1536 /* size of one resource buffer = Ether MTU */ #define KORINA_RDS_MASK (KORINA_NUM_RDS - 1) #define KORINA_TDS_MASK (KORINA_NUM_TDS - 1) #define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc)) -- cgit v1.2.3 From beb0babfb77eab0cbcc7f64a7b8f3545fec5c0ba Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:48:24 -0800 Subject: korina: disable napi on close and restart Without this the driver will crash when the NIC is being restarted. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index e30c2f437d19..65b8487c1896 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -904,6 +904,8 @@ static int korina_restart(struct net_device *dev) korina_free_ring(dev); + napi_disable(&lp->napi); + ret = korina_init(dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: cannot restart device\n", @@ -1070,6 +1072,8 @@ static int korina_close(struct net_device *dev) korina_free_ring(dev); + napi_disable(&lp->napi); + free_irq(lp->rx_irq, dev); free_irq(lp->tx_irq, dev); free_irq(lp->ovr_irq, dev); -- cgit v1.2.3 From 4cf83b664fc14f8262d3013566ca36645f891df2 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:48:59 -0800 Subject: korina: rework korina_rx() for use with napi This function needs an early exit condition to function properly, or else caller assumes napi workload wasn't enough to handle all received packets and korina_rx is called again (and again and again and ...). Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 109 +++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 65b8487c1896..a1d8af7d0bcd 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -353,15 +353,20 @@ static int korina_rx(struct net_device *dev, int limit) struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done]; struct sk_buff *skb, *skb_new; u8 *pkt_buf; - u32 devcs, pkt_len, dmas, rx_free_desc; + u32 devcs, pkt_len, dmas; int count; dma_cache_inv((u32)rd, sizeof(*rd)); for (count = 0; count < limit; count++) { + skb = lp->rx_skb[lp->rx_next_done]; + skb_new = NULL; devcs = rd->devcs; + if ((KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) == 0) + break; + /* Update statistics counters */ if (devcs & ETH_RX_CRC) dev->stats.rx_crc_errors++; @@ -384,63 +389,55 @@ static int korina_rx(struct net_device *dev, int limit) * in Rc32434 (errata ref #077) */ dev->stats.rx_errors++; dev->stats.rx_dropped++; - } - - while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) { - /* init the var. used for the later - * operations within the while loop */ - skb_new = NULL; + } else if ((devcs & ETH_RX_ROK)) { pkt_len = RCVPKT_LENGTH(devcs); - skb = lp->rx_skb[lp->rx_next_done]; - - if ((devcs & ETH_RX_ROK)) { - /* must be the (first and) last - * descriptor then */ - pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; - - /* invalidate the cache */ - dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4); - - /* Malloc up new buffer. */ - skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); - - if (!skb_new) - break; - /* Do not count the CRC */ - skb_put(skb, pkt_len - 4); - skb->protocol = eth_type_trans(skb, dev); - - /* Pass the packet to upper layers */ - netif_receive_skb(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - - /* Update the mcast stats */ - if (devcs & ETH_RX_MP) - dev->stats.multicast++; - - lp->rx_skb[lp->rx_next_done] = skb_new; - } - - rd->devcs = 0; - - /* Restore descriptor's curr_addr */ - if (skb_new) - rd->ca = CPHYSADDR(skb_new->data); - else - rd->ca = CPHYSADDR(skb->data); - - rd->control = DMA_COUNT(KORINA_RBSIZE) | - DMA_DESC_COD | DMA_DESC_IOD; - lp->rd_ring[(lp->rx_next_done - 1) & - KORINA_RDS_MASK].control &= - ~DMA_DESC_COD; - - lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); - rd = &lp->rd_ring[lp->rx_next_done]; - writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); + + /* must be the (first and) last + * descriptor then */ + pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; + + /* invalidate the cache */ + dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4); + + /* Malloc up new buffer. */ + skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); + + if (!skb_new) + break; + /* Do not count the CRC */ + skb_put(skb, pkt_len - 4); + skb->protocol = eth_type_trans(skb, dev); + + /* Pass the packet to upper layers */ + netif_receive_skb(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + + /* Update the mcast stats */ + if (devcs & ETH_RX_MP) + dev->stats.multicast++; + + lp->rx_skb[lp->rx_next_done] = skb_new; } + + rd->devcs = 0; + + /* Restore descriptor's curr_addr */ + if (skb_new) + rd->ca = CPHYSADDR(skb_new->data); + else + rd->ca = CPHYSADDR(skb->data); + + rd->control = DMA_COUNT(KORINA_RBSIZE) | + DMA_DESC_COD | DMA_DESC_IOD; + lp->rd_ring[(lp->rx_next_done - 1) & + KORINA_RDS_MASK].control &= + ~DMA_DESC_COD; + + lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; + dma_cache_wback((u32)rd, sizeof(*rd)); + rd = &lp->rd_ring[lp->rx_next_done]; + writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); } dmas = readl(&lp->rx_dma_regs->dmas); -- cgit v1.2.3 From 4676f63d4c1e2e3530e42cb39bf88a1c1d4d78a5 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:49:39 -0800 Subject: korina: do schedule napi after testing for it The called netif_rx_schedule() does all the work for us: - it checks the return value of netif_rx_schedule_prep() and - if everything is ok calls __netif_rx_schedule(). Before this change, the driver received absolutely nothing. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index a1d8af7d0bcd..7aa05f81fe9e 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -330,7 +330,7 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id) dmas = readl(&lp->rx_dma_regs->dmas); if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) { - netif_rx_schedule_prep(&lp->napi); + netif_rx_schedule(&lp->napi); dmasm = readl(&lp->rx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_DONE | -- cgit v1.2.3 From 60d3f9827ca455e7272681d67a37137c328d7012 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:50:12 -0800 Subject: korina: do tx at the right position Triggering TX before the write to the DMA status mask register leads to transferring packets with maximum payload no matter what the actual packet size is. While here, also trigger RX scheduling after writing the DMA status mask register, like it was in the original driver before it was sent upstream. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 7aa05f81fe9e..dced5e71463a 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -330,13 +330,13 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id) dmas = readl(&lp->rx_dma_regs->dmas); if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) { - netif_rx_schedule(&lp->napi); - dmasm = readl(&lp->rx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmasm); + netif_rx_schedule(&lp->napi); + if (dmas & DMA_STAT_ERR) printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name); @@ -623,12 +623,12 @@ korina_tx_dma_interrupt(int irq, void *dev_id) dmas = readl(&lp->tx_dma_regs->dmas); if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) { - korina_tx(dev); - dmasm = readl(&lp->tx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR), &lp->tx_dma_regs->dmasm); + korina_tx(dev); + if (lp->tx_chain_status == desc_filled && (readl(&(lp->tx_dma_regs->dmandptr)) == 0)) { writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), -- cgit v1.2.3 From 97bc477cbc3d63f2a29c2c81031434b3a082f44c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:50:41 -0800 Subject: korina: fix handling tx_chain_tail Originally this must have been a rewrite error when introducing 'chain_index'. But the original driver did not use the previous chain item everywhere: when altering the address tx_chain_tail points to, it should move forward, not backwards. Also this is not an "index" but rather the penultimate element in the chain, so rename it accordingly. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index dced5e71463a..f20017502519 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -199,7 +199,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) struct korina_private *lp = netdev_priv(dev); unsigned long flags; u32 length; - u32 chain_index; + u32 chain_prev, chain_next; struct dma_desc *td; spin_lock_irqsave(&lp->lock, flags); @@ -231,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Setup the transmit descriptor. */ dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); - chain_index = (lp->tx_chain_tail - 1) & - KORINA_TDS_MASK; + chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; + chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -240,7 +240,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; /* Write to NDPTR */ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &lp->tx_dma_regs->dmandptr); @@ -251,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Link to prev */ - lp->td_ring[chain_index].control &= + lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_index].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = CPHYSADDR(td); /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; /* Write to NDPTR */ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); @@ -270,17 +270,17 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; lp->tx_chain_status = desc_filled; netif_stop_queue(dev); } else { /* Update tail */ td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; - lp->td_ring[chain_index].control &= + lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; - lp->td_ring[chain_index].link = CPHYSADDR(td); - lp->tx_chain_tail = chain_index; + lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->tx_chain_tail = chain_next; } } dma_cache_wback((u32) td, sizeof(*td)); -- cgit v1.2.3 From 5edc7668bbece4238a32943ae7a47135af076948 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:51:15 -0800 Subject: korina: do not stop queue here Apparently this doesn't make sense. Otherwise the queue gets disabled as soon as it's getting empty and can only be resurrected by a driver restart. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index f20017502519..bd33fa915997 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -272,7 +272,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; lp->tx_chain_status = desc_filled; - netif_stop_queue(dev); } else { /* Update tail */ td->control = DMA_COUNT(length) | -- cgit v1.2.3 From 1c5625cf0f121486abad4da0e0251ec67765aa95 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 14 Jan 2009 21:51:48 -0800 Subject: korina: do not use IRQF_SHARED with IRQF_DISABLED As the kernel warning states: "IRQF_DISABLED is not guaranteed on shared IRQs". Since these IRQs' values are hardcoded and my test system doesn't show any shared use of IRQs at all, rather make them non-shared than non-disabled. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index bd33fa915997..1d6e48e13366 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -1000,14 +1000,14 @@ static int korina_open(struct net_device *dev) * that handles the Done Finished * Ovr and Und Events */ ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev); + IRQF_DISABLED, "Korina ethernet Rx", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n", dev->name, lp->rx_irq); goto err_release; } ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev); + IRQF_DISABLED, "Korina ethernet Tx", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n", dev->name, lp->tx_irq); @@ -1016,7 +1016,7 @@ static int korina_open(struct net_device *dev) /* Install handler for overrun error. */ ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev); + IRQF_DISABLED, "Ethernet Overflow", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n", dev->name, lp->ovr_irq); @@ -1025,7 +1025,7 @@ static int korina_open(struct net_device *dev) /* Install handler for underflow error. */ ret = request_irq(lp->und_irq, &korina_und_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev); + IRQF_DISABLED, "Ethernet Underflow", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n", dev->name, lp->und_irq); -- cgit v1.2.3 From fe41cbb164a0dc55f3914a0e4cabe8240410157c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 15 Jan 2009 13:31:15 +0000 Subject: tty: Fix a kref leak in the HSO driver on re-open Signed-off-by: Linus Torvalds --- drivers/net/usb/hso.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index c4918b86ed19..9df04dd1332c 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1297,6 +1297,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) /* setup */ spin_lock_irq(&serial->serial_lock); tty->driver_data = serial; + tty_kref_put(serial->tty); serial->tty = tty_kref_get(tty); spin_unlock_irq(&serial->serial_lock); -- cgit v1.2.3 From d45eb81c3e345fabaf27ef3ab437b85c0bf9fafa Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Thu, 15 Jan 2009 13:31:24 +0000 Subject: tty: Fix double grabbing of a spinlock The HSO changes for kref introduced a recursive spinlock take. All functions which call put_rxbuf_data already have serial->serial_lock grabbed. [Comment to code added-AC] Signed-off-by: Denis Joseph Barrow Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/net/usb/hso.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 9df04dd1332c..e25a58f6ff69 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2044,9 +2044,8 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) return -2; } - spin_lock(&serial->serial_lock); + /* All callers to put_rxbuf_data hold serial_lock */ tty = tty_kref_get(serial->tty); - spin_unlock(&serial->serial_lock); /* Push data to tty */ if (tty) { -- cgit v1.2.3 From 5839b414f9f9d2d6a471988763b61dbf85eb2dba Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Thu, 15 Jan 2009 13:31:34 +0000 Subject: hso serial throttled tty kref fix. This patch is for Alan Cox as it related to the tty layer. Hopefully the hso driver is again relatively stable with this fix. Signed-off-by: Denis Joseph Barrow Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/net/usb/hso.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index e25a58f6ff69..6478bf63f289 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2053,8 +2053,10 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) serial->curr_rx_urb_offset; D1("data to push to tty"); while (write_length_remaining) { - if (test_bit(TTY_THROTTLED, &tty->flags)) + if (test_bit(TTY_THROTTLED, &tty->flags)) { + tty_kref_put(tty); return -1; + } curr_write_len = tty_insert_flip_string (tty, urb->transfer_buffer + serial->curr_rx_urb_offset, -- cgit v1.2.3 From a58c891a53aca81c78f9cbe0572a301042470e96 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 15 Jan 2009 15:29:35 -0800 Subject: b44: GFP_DMA skb should not escape from driver b44 chip has some hardware limitations, that need GFP_DMA bounce buffers in some situations. In order to not deplete DMA zone, we should keep allocated GFP_DMA skb only for driver use. At rx time, we copy such skb to newly allocated skb, reusing existing copybreak infrastructure. On machines with low amount of memory, all skb meet the hardware limitation, so no copy is needed. We detect this situation using a new device flag, set to one if one GFP_DMA skb was ever allocated by b44_alloc_rx_skb(). Previously allocated skb, even outside from DMA zone will then be recycled, to have minimal impact on DMA zone use. Signed-off-by: Eric Dumazet Tested-by: Ionut Leonte Signed-off-by: David S. Miller --- drivers/net/b44.c | 4 +++- drivers/net/b44.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 5ae131c147f9..c38512ebcea6 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -679,6 +679,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) dev_kfree_skb_any(skb); return -ENOMEM; } + bp->force_copybreak = 1; } rh = (struct rx_header *) skb->data; @@ -800,7 +801,7 @@ static int b44_rx(struct b44 *bp, int budget) /* Omit CRC. */ len -= 4; - if (len > RX_COPY_THRESHOLD) { + if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) { int skb_size; skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); if (skb_size < 0) @@ -2152,6 +2153,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev, bp = netdev_priv(dev); bp->sdev = sdev; bp->dev = dev; + bp->force_copybreak = 0; bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE); diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 7db0c84a7950..e678498de6db 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -395,7 +395,7 @@ struct b44 { u32 rx_pending; u32 tx_pending; u8 phy_addr; - + u8 force_copybreak; struct mii_if_info mii_if; }; -- cgit v1.2.3 From d3b924d960a808105180d229b4667061123cc4ef Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 15 Jan 2009 20:43:56 -0800 Subject: mlx4_core: Fix min() warning Fix drivers/net/mlx4/profile.c: In function `mlx4_make_profile': drivers/net/mlx4/profile.c:110: warning: comparison of distinct pointer types lacks a cast This happened because num_possible_cpus() was secretly changed by commit ae7a47e7 ("cpumask: make cpumask.h eat its own dogfood.") from returning "int" to (now) returning "unsigned int". I think that was a good change, so we should just swallow the fallout. Cc: "David S. Miller" Cc: Roland Dreier Cc: Yevgeny Petrilin Cc: Jack Morgenstein Cc: Vladimir Sokolovsky Cc: Michael S. Tsirkin Signed-off-by: Andrew Morton Signed-off-by: Roland Dreier --- drivers/net/mlx4/profile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c index 919fb9eb1b62..cebdf3243ca1 100644 --- a/drivers/net/mlx4/profile.c +++ b/drivers/net/mlx4/profile.c @@ -107,9 +107,9 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, profile[MLX4_RES_AUXC].num = request->num_qp; profile[MLX4_RES_SRQ].num = request->num_srq; profile[MLX4_RES_CQ].num = request->num_cq; - profile[MLX4_RES_EQ].num = min(dev_cap->max_eqs, - dev_cap->reserved_eqs + - num_possible_cpus() + 1); + profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, + dev_cap->reserved_eqs + + num_possible_cpus() + 1); profile[MLX4_RES_DMPT].num = request->num_mpt; profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; profile[MLX4_RES_MTT].num = request->num_mtt; -- cgit v1.2.3 From 3bfafd6b136bea2de9bd96c01b7e3808635a15b2 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 16 Jan 2009 11:03:01 -0800 Subject: netxen: avoid invalid iounmap For NX3031 only one I/O range is mapped, so unmapping other two which are used by older chips, causes this warning on ppc64. "Attempt to iounmap early bolted mapping at 0x0000000000000000" Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 86867405a367..f8e26290a22f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1004,8 +1004,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); - iounmap(adapter->ahw.pci_base1); - iounmap(adapter->ahw.pci_base2); + if (adapter->ahw.pci_base1 != NULL) + iounmap(adapter->ahw.pci_base1); + if (adapter->ahw.pci_base2 != NULL) + iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); pci_disable_device(pdev); -- cgit v1.2.3 From 009777846165fcc49352c0f1487e3a96102884c3 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 16 Jan 2009 11:03:25 -0800 Subject: netxen: include ipv6.h (fixes build failure) Fixes a build error in absence of CONFIG_IPV6: drivers/net/netxen/netxen_nic_main.c:1189: error: implicit declaration of function 'ipv6_hdr' drivers/net/netxen/netxen_nic_main.c:1189: error: invalid type argument of '->' Reported-by: Ingo Molnar Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f8e26290a22f..d854f07ef4d3 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -41,6 +41,7 @@ #include #include #include +#include MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ef15aa490f2e447ce04fe643500b814ef40f6ea9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 9 Jan 2009 21:06:30 +0100 Subject: p54: fix oops caused by bad eeproms This patch fixes a bug that could occur, if it the eeprom is incomplete or partly corrupted. BUG: unable to handle kernel NULL pointer dereference at 00000008 IP: p54_assign_address+0x108/0x15d [p54common] Oops: 0002 [#1] SMP Pid: 12988, comm: phy1 Tainted: P W 2.6.28-rc6-wl #3 RIP: 0010: p54_assign_address+0x108/0x15d [p54common] [...] Call Trace: p54_alloc_skb+0xa3/0xc0 [p54common] p54_scan+0x37/0x204 [p54common] [...] Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c6a370fa9bcb..3b44e8e76030 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1610,7 +1610,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) err: printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); - kfree_skb(skb); + p54_free_skb(dev, skb); return -EINVAL; } -- cgit v1.2.3 From d71038c05970ad0c9d7da6f797803f69e4f91837 Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky Date: Mon, 12 Jan 2009 13:14:27 -0800 Subject: libertas: Fix alignment issues in libertas core Data structures that come over the wire from the WLAN firmware must be packed. This fixes alignment problems on the blackfin architecture and, reportedly, on the AVR32. This is a replacement for the previous version of this patch which had also explicitly used get_unaligned_ macros. As Johannes Berg pointed out, these macros were unnecessary. Signed-off-by: Andrey Yurovsky Signed-off-by: Colin McCabe Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/hostcmd.h | 91 ++++++++++++++++----------------- 1 file changed, 45 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index e173b1b46c23..f6a79a653b7b 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -32,7 +32,7 @@ struct txpd { u8 pktdelay_2ms; /* reserved */ u8 reserved1; -}; +} __attribute__ ((packed)); /* RxPD Descriptor */ struct rxpd { @@ -63,7 +63,7 @@ struct rxpd { /* Pkt Priority */ u8 priority; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_header { __le16 command; @@ -97,7 +97,7 @@ struct enc_key { struct lbs_offset_value { u32 offset; u32 value; -}; +} __attribute__ ((packed)); /* Define general data structure */ /* cmd_DS_GEN */ @@ -107,7 +107,7 @@ struct cmd_ds_gen { __le16 seqnum; __le16 result; void *cmdresp[0]; -}; +} __attribute__ ((packed)); #define S_DS_GEN sizeof(struct cmd_ds_gen) @@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event { * bump this up a bit. */ uint8_t tlv[128]; -}; +} __attribute__ ((packed)); /* * This scan handle Country Information IE(802.11d compliant) @@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan { mrvlietypes_chanlistparamset_t ChanListParamSet; mrvlietypes_ratesparamset_t OpRateSet; #endif -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_scan_rsp { struct cmd_header hdr; @@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp { __le16 bssdescriptsize; uint8_t nr_sets; uint8_t bssdesc_and_tlvbuffer[0]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_get_log { struct cmd_header hdr; @@ -206,33 +206,33 @@ struct cmd_ds_802_11_get_log { __le32 fcserror; __le32 txframe; __le32 wepundecryptable; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_control { struct cmd_header hdr; __le16 action; u16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_multicast_adr { struct cmd_header hdr; __le16 action; __le16 nr_of_adrs; u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_authenticate { u8 macaddr[ETH_ALEN]; u8 authtype; u8 reserved[10]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_deauthenticate { struct cmd_header hdr; u8 macaddr[ETH_ALEN]; __le16 reasoncode; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_associate { u8 peerstaaddr[6]; @@ -251,7 +251,7 @@ struct cmd_ds_802_11_associate { struct cmd_ds_802_11_associate_rsp { struct ieeetypes_assocrsp assocRsp; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_set_wep { struct cmd_header hdr; @@ -265,7 +265,7 @@ struct cmd_ds_802_11_set_wep { /* 40, 128bit or TXWEP */ uint8_t keytype[4]; uint8_t keymaterial[4][16]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_3_get_stat { __le32 xmitok; @@ -274,7 +274,7 @@ struct cmd_ds_802_3_get_stat { __le32 rcverror; __le32 rcvnobuffer; __le32 rcvcrcerror; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_get_stat { __le32 txfragmentcnt; @@ -294,7 +294,7 @@ struct cmd_ds_802_11_get_stat { __le32 txbeacon; __le32 rxbeacon; __le32 wepundecryptable; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_snmp_mib { struct cmd_header hdr; @@ -303,58 +303,58 @@ struct cmd_ds_802_11_snmp_mib { __le16 oid; __le16 bufsize; u8 value[128]; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_reg_map { __le16 buffersize; u8 regmap[128]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_bbp_reg_map { __le16 buffersize; u8 regmap[128]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_rf_reg_map { __le16 buffersize; u8 regmap[64]; __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_mac_reg_access { __le16 action; __le16 offset; __le32 value; -}; +} __attribute__ ((packed)); struct cmd_ds_bbp_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_ds_rf_reg_access { __le16 action; __le16 offset; u8 value; u8 reserved[3]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_radio_control { struct cmd_header hdr; __le16 action; __le16 control; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_beacon_control { __le16 action; __le16 beacon_enable; __le16 beacon_period; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_sleep_params { struct cmd_header hdr; @@ -379,7 +379,7 @@ struct cmd_ds_802_11_sleep_params { /* reserved field, should be set to zero */ __le16 reserved; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_inactivity_timeout { struct cmd_header hdr; @@ -389,7 +389,7 @@ struct cmd_ds_802_11_inactivity_timeout { /* Inactivity timeout in msec */ __le16 timeout; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_channel { struct cmd_header hdr; @@ -399,7 +399,7 @@ struct cmd_ds_802_11_rf_channel { __le16 rftype; /* unused */ __le16 reserved; /* unused */ u8 channellist[32]; /* unused */ -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rssi { /* weighting factor */ @@ -408,21 +408,21 @@ struct cmd_ds_802_11_rssi { __le16 reserved_0; __le16 reserved_1; __le16 reserved_2; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rssi_rsp { __le16 SNR; __le16 noisefloor; __le16 avgSNR; __le16 avgnoisefloor; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_mac_address { struct cmd_header hdr; __le16 action; u8 macadd[ETH_ALEN]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_tx_power { struct cmd_header hdr; @@ -431,7 +431,7 @@ struct cmd_ds_802_11_rf_tx_power { __le16 curlevel; s8 maxlevel; s8 minlevel; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rf_antenna { __le16 action; @@ -439,33 +439,33 @@ struct cmd_ds_802_11_rf_antenna { /* Number of antennas or 0xffff(diversity) */ __le16 antennamode; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_monitor_mode { __le16 action; __le16 mode; -}; +} __attribute__ ((packed)); struct cmd_ds_set_boot2_ver { struct cmd_header hdr; __le16 action; __le16 version; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_fw_wake_method { struct cmd_header hdr; __le16 action; __le16 method; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_sleep_period { struct cmd_header hdr; __le16 action; __le16 period; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_ps_mode { __le16 action; @@ -473,7 +473,7 @@ struct cmd_ds_802_11_ps_mode { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -}; +} __attribute__ ((packed)); struct cmd_confirm_sleep { struct cmd_header hdr; @@ -483,7 +483,7 @@ struct cmd_confirm_sleep { __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_data_rate { struct cmd_header hdr; @@ -491,14 +491,14 @@ struct cmd_ds_802_11_data_rate { __le16 action; __le16 reserved; u8 rates[MAX_RATES]; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_rate_adapt_rateset { struct cmd_header hdr; __le16 action; __le16 enablehwauto; __le16 bitmap; -}; +} __attribute__ ((packed)); struct cmd_ds_802_11_ad_hoc_start { struct cmd_header hdr; @@ -520,7 +520,7 @@ struct cmd_ds_802_11_ad_hoc_result { u8 pad[3]; u8 bssid[ETH_ALEN]; -}; +} __attribute__ ((packed)); struct adhoc_bssdesc { u8 bssid[ETH_ALEN]; @@ -578,7 +578,7 @@ struct MrvlIEtype_keyParamSet { /* key material of size keylen */ u8 key[32]; -}; +} __attribute__ ((packed)); #define MAX_WOL_RULES 16 @@ -590,7 +590,7 @@ struct host_wol_rule { __le16 reserve; __be32 sig_mask; __be32 signature; -}; +} __attribute__ ((packed)); struct wol_config { uint8_t action; @@ -598,8 +598,7 @@ struct wol_config { uint8_t no_rules_in_cmd; uint8_t result; struct host_wol_rule rule[MAX_WOL_RULES]; -}; - +} __attribute__ ((packed)); struct cmd_ds_host_sleep { struct cmd_header hdr; -- cgit v1.2.3 From b657eade2f98b5c689e405bd6e4e445471066380 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 14:33:49 +0200 Subject: ath9k: Fix an operator typo in phy rate validation This was not supposed to be a bitwise AND operation, but a check of two separate conditions. Anyway, the old code happened to result in the same behavior, so this is just changing the code to be easier to understand and also to keep sparse from warning about dubious operators. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 04ab457a8faa..1b71b934bb5e 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -490,7 +490,7 @@ static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) { - if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) + if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) return 0; if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) return 0; -- cgit v1.2.3 From 9d97f2e55e3df44e3b6b4cc58b091501ba7ee0ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Jan 2009 14:35:08 +0200 Subject: ath9k: Fix an operator typo in REG_DOMAIN_2GHZ_MASK Incorrect operator causes the REG_DOMAIN_2GHZ_MASK to be zero which surely was not the goal of this definition. Mask out the 11a flags correctly. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h index 9112c030b1e8..6df1b3b77c25 100644 --- a/drivers/net/wireless/ath9k/regd_common.h +++ b/drivers/net/wireless/ath9k/regd_common.h @@ -228,7 +228,7 @@ enum { }; #define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \ - (!(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) + (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) #define REG_DOMAIN_5GHZ_MASK REQ_MASK static struct reg_dmn_pair_mapping regDomainPairs[] = { -- cgit v1.2.3 From 73e1a65d3c4a013f6fa56e47133be95143a75fe3 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 8 Jan 2009 10:19:58 -0800 Subject: iwlwifi: remove CMD_WANT_SKB flag if send_cmd_sync failure In function iwl_send_cmd_sync(), if the flag CMD_WANT_SKB is set but we are not provided with a valid SKB (cmd->meta.u.skb == NULL), we need to remove the CMD_WANT_SKB flag from the TX cmd queue. Otherwise in case the cmd comes in later, it will possibly set an invalid address. Thus it causes an invalid memory access. This fixed the bug http://bugzilla.kernel.org/show_bug.cgi?id=11326. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8c71ad4f88c5..4b35b30e493e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -224,7 +224,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) IWL_ERROR("Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; - goto out; + goto cancel; } ret = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d64580805d6e..15f5655c636e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -745,7 +745,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ IWL_ERROR("Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; - goto out; + goto cancel; } ret = 0; -- cgit v1.2.3 From e223b6dc051ad030a70d5c6ed6226b95bdfc3af7 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Wed, 14 Jan 2009 00:00:13 +0200 Subject: rt2x00: fix a wrong parameter for __test_and_clear_bit() in rt2x00rfkill_free(). When running modprobe rt73usb, and then rmmod rt73usb, and then iwconfig, the wlan0 device does not disappear. When repeating this process again, we get a kernel Oops errors and "BUG: unable to handle kernel paging request..." message in the kernel log. The reason for this is that there is an error in rt2x00rfkill_free(), which is called in the process of removing the device (rt2x00lib_remove_dev() in rt2x00dev.c). rt2x00rfkill_free() clears the RFKILL_STATE_ALLOCATED bit , which is bit number 1 () in rt2x00dev->flags instead of in rt2x00dev->rfkill_state. As a result, when checking the DEVICE_STATE_REGISTERED_HW bit (bit number 1 in rt2x00dev->flags) in rt2x00lib_remove_hw() it is **unset**, and we wrongly **don't** call ieee80211_unregister_hw(). This patch corrects this: the parameter for __test_and_clear_bit() in rt2x00rfkill_free() should be &rt2x00dev->rfkill_state and not &rt2x00dev->flags. Signed-off-by: Rami Rosen Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index c3f53a92180a..3298cae1e12d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -162,7 +162,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { - if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags)) + if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; cancel_delayed_work_sync(&rt2x00dev->rfkill_work); -- cgit v1.2.3 From 275719089bfe7dbf446b72c3e520966e7fa42b6a Mon Sep 17 00:00:00 2001 From: Artur Skawina Date: Thu, 15 Jan 2009 21:07:03 +0100 Subject: p54: set_tim must be atomic. Fix for: BUG: scheduling while atomic: named/2004/0x10000200 Pid: 2004, comm: named Not tainted 2.6.29-rc1-00271-ge9fa6b0 #45 Call Trace: [] schedule+0x2a7/0x320 [] __alloc_skb+0x34/0x110 [] __cond_resched+0x13/0x30 [] _cond_resched+0x2d/0x40 [] kmem_cache_alloc+0x95/0xc0 [] check_object+0xc4/0x230 [] __alloc_skb+0x34/0x110 [] p54_alloc_skb+0x71/0xf0 [] p54_set_tim+0x3f/0xa0 [] sta_info_set_tim_bit+0x64/0x80 [] invoke_tx_handlers+0xd57/0xd80 [] free_debug_processing+0x197/0x210 [] pskb_expand_head+0xf5/0x170 [] __ieee80211_tx_prepare+0x164/0x2f0 [] ieee80211_skb_resize+0x6d/0xe0 [] ieee80211_master_start_xmit+0x23f/0x550 [] __slab_alloc+0x2b8/0x4f0 [] getnstimeofday+0x51/0x120 [] dev_hard_start_xmit+0x1db/0x240 [] __qdisc_run+0x1ab/0x200 [] __run_hrtimer+0x31/0xf0 [] dev_queue_xmit+0x247/0x500 [] ieee80211_subif_start_xmit+0x356/0x7d0 [] packet_rcv_spkt+0x37/0x150 [] packet_rcv_spkt+0x37/0x150 [] dev_hard_start_xmit+0x1db/0x240 [] __qdisc_run+0x1ab/0x200 [] dev_queue_xmit+0x247/0x500 [] neigh_resolve_output+0xe2/0x200 [] ip_finish_output+0x0/0x290 [] ip_finish_output+0x1e7/0x290 [] ip_local_out+0x15/0x20 [] ip_push_pending_frames+0x272/0x380 [] udp_push_pending_frames+0x146/0x3a0 [] udp_sendmsg+0x2fa/0x6b0 [] inet_sendmsg+0x37/0x70 [] sock_sendmsg+0xbe/0x100 [] autoremove_wake_function+0x0/0x50 [] __wake_up_common+0x43/0x70 [] copy_from_user+0x32/0x130 [] copy_from_user+0x32/0x130 [] verify_iovec+0x2e/0xb0 [] sys_sendmsg+0x17f/0x290 [] pipe_write+0x29a/0x570 [] update_wall_time+0x492/0x8e0 [] getnstimeofday+0x51/0x120 [] sched_slice+0x3d/0x80 [] getnstimeofday+0x51/0x120 [] hrtimer_forward+0x147/0x1a0 [] lapic_next_event+0x10/0x20 [] clockevents_program_event+0xa3/0x170 [] sys_socketcall+0xa4/0x290 [] smp_apic_timer_interrupt+0x40/0x70 [] sysenter_do_call+0x12/0x25 Signed-off-by: Artur Skawina Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 3b44e8e76030..ae31e3775e0c 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1147,7 +1147,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(struct p54_hdr) + sizeof(*tim), - P54_CONTROL_TYPE_TIM, GFP_KERNEL); + P54_CONTROL_TYPE_TIM, GFP_ATOMIC); if (!skb) return -ENOMEM; -- cgit v1.2.3 From 674743033c1ae9f7cc94e1e0037f6f719e6d1d67 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 16 Jan 2009 19:46:28 +0100 Subject: p54: fix p54_set_key's return code p54 doesn't support AES-128-CMAC offload. This patch will fix the noisy mac80211 warnings, when 802.11w is enabled: mac80211-phy189: failed to set key (4, ff:ff:ff:ff:ff:ff) to hardware (-22) mac80211-phy189: failed to set key (5, ff:ff:ff:ff:ff:ff) to hardware (-22) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ae31e3775e0c..12d0717c3992 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2077,7 +2077,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, algo = P54_CRYPTO_AESCCMP; break; default: - return -EINVAL; + return -EOPNOTSUPP; } } -- cgit v1.2.3 From 70b9986ca4baaf6deb6f0e01d50f72457579adea Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:48 +0000 Subject: bnx2x: Free IRQ Error check could result with not freeing the IRQ Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7c533797c064..ce98ecf8cb1c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6684,6 +6684,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); bnx2x_stats_handle(bp, STATS_EVENT_STOP); + /* Release IRQs */ + bnx2x_free_irq(bp); + /* Wait until tx fast path tasks complete */ for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; @@ -6711,9 +6714,6 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Give HW time to discard old tx messages */ msleep(1); - /* Release IRQs */ - bnx2x_free_irq(bp); - if (CHIP_IS_E1(bp)) { struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); -- cgit v1.2.3 From 693fc0d14334859430733ab902adac182fdd8153 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:52 +0000 Subject: bnx2x: Handling probe failures Failures in the probe not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ce98ecf8cb1c..911067586a4a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10269,17 +10269,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return rc; } - rc = register_netdev(dev); - if (rc) { - dev_err(&pdev->dev, "Cannot register net device\n"); - goto init_one_exit; - } - pci_set_drvdata(pdev, dev); rc = bnx2x_init_bp(bp); + if (rc) + goto init_one_exit; + + rc = register_netdev(dev); if (rc) { - unregister_netdev(dev); + dev_err(&pdev->dev, "Cannot register net device\n"); goto init_one_exit; } -- cgit v1.2.3 From b4661739c67acd15a02f8e112f8cc52d24b609ed Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:56 +0000 Subject: bnx2x: Potential race after iSCSI boot The lock was release too soon. Make sure the HW is marked as locked until the boot driver was unloaded from FW perspective Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 911067586a4a..70fc61033ddf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6874,10 +6874,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) */ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); - if (val == 0x7) - REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); - if (val == 0x7) { u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* save our func */ @@ -6885,6 +6881,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) u32 swap_en; u32 swap_val; + /* clear the UNDI indication */ + REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); + BNX2X_DEV_INFO("UNDI is active! reset device\n"); /* try unload UNDI on port 0 */ @@ -6910,6 +6909,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bnx2x_fw_command(bp, reset_code); } + /* now it's safe to release the lock */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + REG_WR(bp, (BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0), 0x1000); @@ -6954,7 +6956,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bp->fw_seq = (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); - } + + } else + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); } } -- cgit v1.2.3 From af2464011f0954785687071b298f066f6cbb1c84 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:43:59 +0000 Subject: bnx2x: Wrong HDR offset in CAM Has a negative side effect when sending MAC update with no content (as done in the self-test) Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 70fc61033ddf..8f8271d76db6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6144,7 +6144,7 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set) * multicast 64-127:port0 128-191:port1 */ config->hdr.length_6b = 2; - config->hdr.offset = port ? 31 : 0; + config->hdr.offset = port ? 32 : 0; config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -8910,7 +8910,10 @@ static int bnx2x_test_intr(struct bnx2x *bp) return -ENODEV; config->hdr.length_6b = 0; - config->hdr.offset = 0; + if (CHIP_IS_E1(bp)) + config->hdr.offset = (BP_PORT(bp) ? 32 : 0); + else + config->hdr.offset = BP_FUNC(bp); config->hdr.client_id = BP_CL_ID(bp); config->hdr.reserved1 = 0; @@ -9863,7 +9866,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) for (; i < old; i++) { if (CAM_IS_INVALID(config-> config_table[i])) { - i--; /* already invalidated */ + /* already invalidated */ break; } /* invalidate */ -- cgit v1.2.3 From 5a40e08e666e8caa1227333de41fd1e2cd84d4f5 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:04 +0000 Subject: bnx2x: Read chip ID Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 8f8271d76db6..7ee6a211f9ba 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6975,7 +6975,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) id |= ((val & 0xf) << 12); val = REG_RD(bp, MISC_REG_CHIP_METAL); id |= ((val & 0xff) << 4); - REG_RD(bp, MISC_REG_BOND_ID); + val = REG_RD(bp, MISC_REG_BOND_ID); id |= (val & 0xf); bp->common.chip_id = id; bp->link_params.chip_id = bp->common.chip_id; -- cgit v1.2.3 From 2add3acb11a26cc14b54669433ae6ace6406cbf2 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:07 +0000 Subject: bnx2x: Block nvram access when the device is inactive Don't dump eeprom when bnx2x adapter is down. Running ethtool -e causes an eeh without it when the device is down Signed-off-by: Paul Larson Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7ee6a211f9ba..ca5090c3341e 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8107,6 +8107,9 @@ static int bnx2x_get_eeprom(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); int rc; + if (!netif_running(dev)) + return -EAGAIN; + DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n" DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n", eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset, -- cgit v1.2.3 From 632da4d66324b5baf947a048dd1f1e9093b6dd90 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:10 +0000 Subject: bnx2x: Overstepping array bounds If the page size is > 8KB this violation happens Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ca5090c3341e..2e00da6ab172 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9427,6 +9427,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) return rc; } +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* check if packet requires linearization (packet is too fragmented) */ static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb, u32 xmit_type) @@ -9504,6 +9505,7 @@ exit_lbl: return to_copy; } +#endif /* called with netif_tx_lock * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call @@ -9544,6 +9546,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr, ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type); +#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3) /* First, check if we need to linearize the skb (due to FW restrictions) */ if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) { @@ -9556,6 +9559,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } +#endif /* Please read carefully. First we use one BD which we mark as start, -- cgit v1.2.3 From 6c55c3cdc86881383075a933594748b30dd0054b Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:13 +0000 Subject: bnx2x: 1G-10G toggling race The HW should be configured so fast toggling between 1G and 10G will not be missed. Make sure that the HW is re-configured in full Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index fefa6ab13064..d9e1cfcd06dd 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -317,6 +317,9 @@ static u8 bnx2x_emac_enable(struct link_params *params, val &= ~0x810; EMAC_WR(bp, EMAC_REG_EMAC_MODE, val); + /* enable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1); + /* enable emac for jumbo packets */ EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE, (EMAC_RX_MTU_SIZE_JUMBO_ENA | @@ -1609,7 +1612,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, u32 gp_status) { struct bnx2x *bp = params->bp; - + u16 new_line_speed; u8 rc = 0; vars->link_status = 0; @@ -1629,7 +1632,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, switch (gp_status & GP_STATUS_SPEED_MASK) { case GP_STATUS_10M: - vars->line_speed = SPEED_10; + new_line_speed = SPEED_10; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_10TFD; else @@ -1637,7 +1640,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; case GP_STATUS_100M: - vars->line_speed = SPEED_100; + new_line_speed = SPEED_100; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_100TXFD; else @@ -1646,7 +1649,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, case GP_STATUS_1G: case GP_STATUS_1G_KX: - vars->line_speed = SPEED_1000; + new_line_speed = SPEED_1000; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_1000TFD; else @@ -1654,7 +1657,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; case GP_STATUS_2_5G: - vars->line_speed = SPEED_2500; + new_line_speed = SPEED_2500; if (vars->duplex == DUPLEX_FULL) vars->link_status |= LINK_2500TFD; else @@ -1671,32 +1674,32 @@ static u8 bnx2x_link_settings_status(struct link_params *params, case GP_STATUS_10G_KX4: case GP_STATUS_10G_HIG: case GP_STATUS_10G_CX4: - vars->line_speed = SPEED_10000; + new_line_speed = SPEED_10000; vars->link_status |= LINK_10GTFD; break; case GP_STATUS_12G_HIG: - vars->line_speed = SPEED_12000; + new_line_speed = SPEED_12000; vars->link_status |= LINK_12GTFD; break; case GP_STATUS_12_5G: - vars->line_speed = SPEED_12500; + new_line_speed = SPEED_12500; vars->link_status |= LINK_12_5GTFD; break; case GP_STATUS_13G: - vars->line_speed = SPEED_13000; + new_line_speed = SPEED_13000; vars->link_status |= LINK_13GTFD; break; case GP_STATUS_15G: - vars->line_speed = SPEED_15000; + new_line_speed = SPEED_15000; vars->link_status |= LINK_15GTFD; break; case GP_STATUS_16G: - vars->line_speed = SPEED_16000; + new_line_speed = SPEED_16000; vars->link_status |= LINK_16GTFD; break; @@ -1708,6 +1711,15 @@ static u8 bnx2x_link_settings_status(struct link_params *params, break; } + /* Upon link speed change set the NIG into drain mode. + Comes to deals with possible FIFO glitch due to clk change + when speed is decreased without link down indicator */ + if (new_line_speed != vars->line_speed) { + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + + params->port*4, 0); + msleep(1); + } + vars->line_speed = new_line_speed; vars->link_status |= LINK_STATUS_SERDES_LINK; if ((params->req_line_speed == SPEED_AUTO_NEG) && @@ -4194,6 +4206,11 @@ static u8 bnx2x_update_link_down(struct link_params *params, /* activate nig drain */ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); + /* disable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); + + msleep(10); + /* reset BigMac */ bnx2x_bmac_rx_disable(bp, params->port); REG_WR(bp, GRCBASE_MISC + @@ -4238,6 +4255,7 @@ static u8 bnx2x_update_link_up(struct link_params *params, /* update shared memory */ bnx2x_update_mng(params, vars->link_status); + msleep(20); return rc; } /* This function should called upon link interrupt */ @@ -4276,6 +4294,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); + /* disable emac */ + REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); + ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); /* Check external link change only for non-direct */ -- cgit v1.2.3 From 3858276b7198074bf3570470463808627f0c9e31 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:16 +0000 Subject: bnx2x: Prevent self test loopback failures Setting loopback requires time to take effect Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index d9e1cfcd06dd..4ce107c125d1 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -3583,7 +3583,7 @@ static void bnx2x_set_xgxs_loopback(struct link_params *params, (MDIO_REG_BANK_CL73_IEEEB0 + (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), 0x6041); - + msleep(200); /* set aer mmd back */ bnx2x_set_aer_mmd(params, vars); -- cgit v1.2.3 From 44722d1d216c9dd4536de5f88fe8320b07e68a96 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:21 +0000 Subject: bnx2x: Legacy speeds autoneg failures 10M/100M autoneg was not establishing link. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 4ce107c125d1..2fd6be0cca13 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -3882,9 +3882,15 @@ static u8 bnx2x_link_initialize(struct link_params *params, } if (vars->phy_flags & PHY_XGXS_FLAG) { - if (params->req_line_speed && + if ((params->req_line_speed && ((params->req_line_speed == SPEED_100) || - (params->req_line_speed == SPEED_10))) { + (params->req_line_speed == SPEED_10))) || + (!params->req_line_speed && + (params->speed_cap_mask >= + PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) && + (params->speed_cap_mask < + PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) + )) { vars->phy_flags |= PHY_SGMII_FLAG; } else { vars->phy_flags &= ~PHY_SGMII_FLAG; -- cgit v1.2.3 From 16b311cc29806bb968746c1a752a087b32841af9 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:24 +0000 Subject: bnx2x: Handling PHY FW load failure If the default PHY version (0x4321) is read - the PHY FW load failed Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_link.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 2fd6be0cca13..b4527a4a60e3 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -4404,10 +4404,11 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) ext_phy_addr[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &fw_ver1); - if (fw_ver1 == 0) { + if (fw_ver1 == 0 || fw_ver1 == 0x4321) { DP(NETIF_MSG_LINK, - "bnx2x_8073_common_init_phy port %x " - "fw Download failed\n", port); + "bnx2x_8073_common_init_phy port %x:" + "Download failed. fw version = 0x%x\n", + port, fw_ver1); return -EINVAL; } -- cgit v1.2.3 From e47d7e6eb841c1850f0e69b95ae6cf3c86881f53 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:44:28 +0000 Subject: bnx2x: Driver description update The Driver supports the 57711 and 57711E as well but the description was out of date Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 2e00da6ab172..dc05e37c581d 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -69,7 +69,7 @@ static char version[] __devinitdata = DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Eliezer Tamir"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -- cgit v1.2.3 From 237907c1ded8a1a447cea7c4f97ab853e8b46052 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Wed, 14 Jan 2009 06:42:44 +0000 Subject: bnx2x: Barriers for the compiler To make sure no swapping are made by the compiler, changed HAS_WORK to inline functions and added all the necessary barriers Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 9 +-------- drivers/net/bnx2x_main.c | 37 ++++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 6fcccef4cf3d..18f60aa3efdd 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -271,14 +271,7 @@ struct bnx2x_fastpath { #define bnx2x_fp(bp, nr, var) (bp->fp[nr].var) -#define BNX2X_HAS_TX_WORK(fp) \ - ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) || \ - (fp->tx_pkt_prod != fp->tx_pkt_cons)) - -#define BNX2X_HAS_RX_WORK(fp) \ - (fp->rx_comp_cons != rx_cons_sb) - -#define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp)) +#define BNX2X_HAS_WORK(fp) (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)) /* MC hsi */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index dc05e37c581d..3236527477a3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -733,6 +733,17 @@ static u16 bnx2x_ack_int(struct bnx2x *bp) * fast path service functions */ +static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) +{ + u16 tx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); + return ((fp->tx_pkt_prod != tx_cons_sb) || + (fp->tx_pkt_prod != fp->tx_pkt_cons)); +} + /* free skb in the packet ring at pos idx * return idx of last bd freed */ @@ -6693,7 +6704,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (BNX2X_HAS_TX_WORK(fp)) { + while (bnx2x_has_tx_work(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { @@ -9281,6 +9292,18 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) return 0; } +static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) +{ + u16 rx_cons_sb; + + /* Tell compiler that status block fields can change */ + barrier(); + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; + return (fp->rx_comp_cons != rx_cons_sb); +} + /* * net_device service functions */ @@ -9291,7 +9314,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) napi); struct bnx2x *bp = fp->bp; int work_done = 0; - u16 rx_cons_sb; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -9304,19 +9326,12 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) bnx2x_update_fpsb_idx(fp); - if (BNX2X_HAS_TX_WORK(fp)) + if (bnx2x_has_tx_work(fp)) bnx2x_tx_int(fp, budget); - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; - if (BNX2X_HAS_RX_WORK(fp)) + if (bnx2x_has_rx_work(fp)) work_done = bnx2x_rx_int(fp, budget); - rmb(); /* BNX2X_HAS_WORK() reads the status block */ - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; /* must not complete if we consumed full budget */ if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) { -- cgit v1.2.3 From d05c26ce690e867aabfc7d708d481e0f86f23496 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Sat, 17 Jan 2009 23:26:13 -0800 Subject: bnx2x: Version update Updating the version and the year of updated files Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_link.c | 2 +- drivers/net/bnx2x_main.c | 6 +++--- drivers/net/bnx2x_reg.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 18f60aa3efdd..15a5cf0f676b 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index b4527a4a60e3..aea26b4dc453 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -1,4 +1,4 @@ -/* Copyright 2008 Broadcom Corporation +/* Copyright 2008-2009 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 3236527477a3..074374ff93f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.23" -#define DRV_MODULE_RELDATE "2008/11/03" +#define DRV_MODULE_VERSION "1.45.24" +#define DRV_MODULE_RELDATE "2009/01/14" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index a67b0c358ae4..d084e5fc4b51 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2008 Broadcom Corporation + * Copyright (c) 2007-2009 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From 39eddb4c3970e9aadbc87b8a7cab7b4fefff077f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 18 Jan 2009 21:57:35 -0800 Subject: macb: avoid lockup when TGO during underrun MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In rare cases when an underrun occur, all macb buffers where consumed and the netif_queue was stopped infinitely. This happens then the TGO (transfer ongoing) bit in the TSR is set (and UND). It seems like clening up after the underrun makes the driver and the macb hardware end up in an inconsistent state. The result of this is that in the following calls to macb_tx no TX buffers are released -> the netif_queue was stopped, and never woken up again. The solution is to disable the transmitter, if TGO is set, before clening up after the underrun, and re-enable the transmitter when the cleaning up is done. Signed-off-by: Richard Röjfors Signed-off-by: David S. Miller --- drivers/net/macb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index a04da4ecaa88..f6c4936e2fa8 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -321,6 +321,10 @@ static void macb_tx(struct macb *bp) printk(KERN_ERR "%s: TX underrun, resetting buffers\n", bp->dev->name); + /* Transfer ongoing, disable transmitter, to avoid confusion */ + if (status & MACB_BIT(TGO)) + macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE)); + head = bp->tx_head; /*Mark all the buffer as used to avoid sending a lost buffer*/ @@ -343,6 +347,10 @@ static void macb_tx(struct macb *bp) } bp->tx_head = bp->tx_tail = 0; + + /* Enable the transmitter again */ + if (status & MACB_BIT(TGO)) + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE)); } if (!(status & MACB_BIT(COMP))) -- cgit v1.2.3 From eed087e367591fc08490d7c6c2779b4b72c8f20c Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Jan 2009 22:01:32 -0800 Subject: cxgb3: Fix LRO misalignment The lro manager's frag_align_pad setting was missing, leading to misaligned access to the skb passed up to the stack. Tested-by: Rick Jones Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 14f9fb3e8795..379a1324db4e 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2104,6 +2104,7 @@ static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr) { lro_mgr->dev = qs->netdev; lro_mgr->features = LRO_F_NAPI; + lro_mgr->frag_align_pad = NET_IP_ALIGN; lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; lro_mgr->max_desc = T3_MAX_LRO_SES; -- cgit v1.2.3 From 6a2fe9834e578590f4a2fbe18a574465ab0e127c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:55 +0000 Subject: korina: fix loop back of receive descriptors After the last loop iteration, i has the value RC32434_NUM_RDS and therefore leads to an index overflow when used afterwards to address the last element. This is yet another another bug introduced when rewriting parts of the driver for upstream preparation, as the original driver used 'RC32434_NUM_RDS - 1' instead. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 1d6e48e13366..67fbdf40aceb 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -769,11 +769,12 @@ static void korina_alloc_ring(struct net_device *dev) lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]); } - /* loop back */ - lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]); - lp->rx_next_done = 0; + /* loop back receive descriptors, so the last + * descriptor points to the first one */ + lp->rd_ring[i - 1].link = CPHYSADDR(&lp->rd_ring[0]); + lp->rd_ring[i - 1].control |= DMA_DESC_COD; - lp->rd_ring[i].control |= DMA_DESC_COD; + lp->rx_next_done = 0; lp->rx_chain_head = 0; lp->rx_chain_tail = 0; lp->rx_chain_status = desc_empty; -- cgit v1.2.3 From 63a66c6c0debcae70183849121734fd4809e1dde Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:56 +0000 Subject: korina: adjust headroom for new skb's also This is copy and paste from the original driver. As skb_reserve() is also called within korina_alloc_ring() when initially allocating the receive descriptors, the same should be done when allocating new space after passing an skb to upper layers. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 67fbdf40aceb..60ae7bfb1d9b 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -416,6 +416,9 @@ static int korina_rx(struct net_device *dev, int limit) if (devcs & ETH_RX_MP) dev->stats.multicast++; + /* 16 bit align */ + skb_reserve(skb_new, 2); + lp->rx_skb[lp->rx_next_done] = skb_new; } -- cgit v1.2.3 From e85bf47e6ded66ea138f692fe149c00a4998afe8 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Jan 2009 12:29:57 +0000 Subject: korina: drop leftover assignment As the assigned value is being overwritten shortly after, it can be dropped and so the whole variable definition moved to the start of the function. Signed-off-by: Phil Sutter Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/korina.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 60ae7bfb1d9b..75010cac76ac 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -743,6 +743,7 @@ static struct ethtool_ops netdev_ethtool_ops = { static void korina_alloc_ring(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); + struct sk_buff *skb; int i; /* Initialize the transmit descriptors */ @@ -758,8 +759,6 @@ static void korina_alloc_ring(struct net_device *dev) /* Initialize the receive descriptors */ for (i = 0; i < KORINA_NUM_RDS; i++) { - struct sk_buff *skb = lp->rx_skb[i]; - skb = dev_alloc_skb(KORINA_RBSIZE + 2); if (!skb) break; -- cgit v1.2.3 From 15005a320473b8d3676b878deb29bbe738ef9027 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 19 Jan 2009 16:54:13 -0800 Subject: ixgbe: fix dca issue with relaxed ordering turned on The is an issue where setting Relaxed Ordering (RO) bit (in a PCI-E write transaction) on 82598 causing the chipset to drop DCA hints. This patch forces RO not to be set for descriptors as well as payload. This will only be in effect while DCA is enabled and no performance difference was noticed in testing. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 3 +++ drivers/net/ixgbe/ixgbe_type.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index acef3c65cd2c..92d9b17a081a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -318,6 +318,9 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN; rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN; + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN); + rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN | + IXGBE_DCA_RXCTRL_DESC_HSRO_EN); IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl); rx_ring->cpu = cpu; } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 83a11ff9ffd1..f011c57c9205 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -404,6 +404,9 @@ #define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ #define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ +#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DESC_WRO_EN (1 << 13) /* DCA Rx wr Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DESC_HSRO_EN (1 << 15) /* DCA Rx Split Header RO */ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ -- cgit v1.2.3 From 068c89b014ebd27b1c09c3c772e9d982988e7786 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Mon, 19 Jan 2009 16:54:36 -0800 Subject: ixgbe: fix tag stripping for VLAN ID 0 Register VLAN ID 0 so that frames with VLAN ID 0 are received and get their tag stripped when ixgbe is not in DCB mode. VLAN ID 0 means that the frame is 'priority tagged' only - it is not a VLAN, but the priority value is the tag in valid. The functions ixgbe_vlan_rx_register() and ixgbe_vlan_rx_kill_vid() were moved up a couple functions to correct compiling issues with this change. Signed-off-by: Don Skidmore Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Eric W Multanen Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 53 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 92d9b17a081a..bf36737e2ec7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1744,6 +1744,32 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); } +static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + + /* add VID to filter table */ + hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true); +} + +static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_disable(adapter); + + vlan_group_set_device(adapter->vlgrp, vid, NULL); + + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + ixgbe_irq_enable(adapter); + + /* remove VID from filter table */ + hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false); +} + static void ixgbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { @@ -1763,6 +1789,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, ctrl |= IXGBE_VLNCTRL_VME; ctrl &= ~IXGBE_VLNCTRL_CFIEN; IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); + ixgbe_vlan_rx_add_vid(netdev, 0); if (grp) { /* enable VLAN tag insert/strip */ @@ -1776,32 +1803,6 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, ixgbe_irq_enable(adapter); } -static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_hw *hw = &adapter->hw; - - /* add VID to filter table */ - hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true); -} - -static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) -{ - struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_hw *hw = &adapter->hw; - - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_disable(adapter); - - vlan_group_set_device(adapter->vlgrp, vid, NULL); - - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable(adapter); - - /* remove VID from filter table */ - hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false); -} - static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) { ixgbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); -- cgit v1.2.3 From 1da100bb47ef32cb43bb6a365f64183898f830b5 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Mon, 19 Jan 2009 16:55:03 -0800 Subject: ixgbe: Fix usage of netif_*_all_queues() with netif_carrier_{off|on}() netif_carrier_off() is sufficient to stop Tx into the driver. Stopping the Tx queues is redundant and unnecessary. By the same token, netif_carrier_on() will be sufficient to re-enable Tx, so waking the queues is unnecessary. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bf36737e2ec7..d2f4d5f508b7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2078,6 +2078,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + /* enable transmits */ + netif_tx_start_all_queues(netdev); + /* bring the link up in the watchdog, this could race with our first * link up interrupt but shouldn't be a problem */ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; @@ -3479,7 +3482,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) (FLOW_TX ? "TX" : "None")))); netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); } else { /* Force detection of hung controller */ adapter->detect_tx_hung = true; @@ -3491,7 +3493,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) printk(KERN_INFO "ixgbe: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); } } @@ -4222,7 +4223,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); -- cgit v1.2.3 From 9e9fd12dc0679643c191fc9795a3021807e77de4 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 19 Jan 2009 16:57:45 -0800 Subject: tg3: Fix firmware loading This patch modifies how the tg3 driver handles device firmware. The patch starts by consolidating David Woodhouse's earlier patch under the same name. Specifically, the patch moves the request_firmware call into a separate tg3_request_firmware() function and calls that function from tg3_open() rather than tg3_init_one(). The patch then goes on to limit the number of devices that will make request_firmware calls. The original firmware patch unnecessarily requested TSO firmware for devices that did not need it. This patch reduces the set of devices making TSO firmware patches to approximately the following device set : 5703, 5704, and 5705. Finally, the patch reduces the effects of a request_firmware() failure. For those devices that are requesting TSO firmware, the driver will turn off the TSO capability. If TSO firmware becomes available at a later time, the device can be closed and then opened again to reacquire the TSO capability. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 81 ++++++++++++++++++++++++++++++++++--------------------- drivers/net/tg3.h | 1 + 2 files changed, 51 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5e2dbaee125b..8b3f84685387 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7535,11 +7535,58 @@ static int tg3_test_msi(struct tg3 *tp) return err; } +static int tg3_request_firmware(struct tg3 *tp) +{ + const __be32 *fw_data; + + if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { + printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", + tp->dev->name, tp->fw_needed); + return -ENOENT; + } + + fw_data = (void *)tp->fw->data; + + /* Firmware blob starts with version numbers, followed by + * start address and _full_ length including BSS sections + * (which must be longer than the actual data, of course + */ + + tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ + if (tp->fw_len < (tp->fw->size - 12)) { + printk(KERN_ERR "%s: bogus length %d in \"%s\"\n", + tp->dev->name, tp->fw_len, tp->fw_needed); + release_firmware(tp->fw); + tp->fw = NULL; + return -EINVAL; + } + + /* We no longer need firmware; we have it. */ + tp->fw_needed = NULL; + return 0; +} + static int tg3_open(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); int err; + if (tp->fw_needed) { + err = tg3_request_firmware(tp); + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { + if (err) + return err; + } else if (err) { + printk(KERN_WARNING "%s: TSO capability disabled.\n", + tp->dev->name); + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { + printk(KERN_NOTICE "%s: TSO capability restored.\n", + tp->dev->name); + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; + } + } + netif_carrier_off(tp->dev); err = tg3_set_power_state(tp, PCI_D0); @@ -12934,7 +12981,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, struct net_device *dev; struct tg3 *tp; int err, pm_cap; - const char *fw_name = NULL; char str[40]; u64 dma_mask, persist_dma_mask; @@ -13091,7 +13137,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) - fw_name = FIRMWARE_TG3; + tp->fw_needed = FIRMWARE_TG3; if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; @@ -13104,37 +13150,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; } else { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; - } - if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - fw_name = FIRMWARE_TG3TSO5; + tp->fw_needed = FIRMWARE_TG3TSO5; else - fw_name = FIRMWARE_TG3TSO; - } - - if (fw_name) { - const __be32 *fw_data; - - err = request_firmware(&tp->fw, fw_name, &tp->pdev->dev); - if (err) { - printk(KERN_ERR "tg3: Failed to load firmware \"%s\"\n", - fw_name); - goto err_out_iounmap; - } - - fw_data = (void *)tp->fw->data; - - /* Firmware blob starts with version numbers, followed by - start address and _full_ length including BSS sections - (which must be longer than the actual data, of course */ - - tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ - if (tp->fw_len < (tp->fw->size - 12)) { - printk(KERN_ERR "tg3: bogus length %d in \"%s\"\n", - tp->fw_len, fw_name); - err = -EINVAL; - goto err_out_fw; - } + tp->fw_needed = FIRMWARE_TG3TSO; } /* TSO is on by default on chips that support hardware TSO. diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ae5da603c6af..508def3e077f 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2764,6 +2764,7 @@ struct tg3 { struct ethtool_coalesce coal; /* firmware info */ + const char *fw_needed; const struct firmware *fw; u32 fw_len; /* includes BSS */ }; -- cgit v1.2.3 From e0c6ef9388b58f297937fc9651331941d1579b25 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 19 Jan 2009 17:16:00 -0800 Subject: Revert "mv643xx_eth: use longer DMA bursts". This reverts commit cd4ccf76bfd2c36d351e68be7e6a597268f98a1a. On the Pegasos board, we can't do DMA burst that are longer than one cache line. For now, go back to using 32 byte DMA bursts for all mv643xx_eth platforms -- we can switch the ARM-based platforms back to doing long 128 byte bursts in the next development cycle. Signed-off-by: Lennert Buytenhek Reported-by: Alan Curry Reported-by: Gabriel Paubert Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 7253a499d9c8..e2aa468d40f1 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -136,21 +136,23 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* * SDMA configuration register. */ +#define RX_BURST_SIZE_4_64BIT (2 << 1) #define RX_BURST_SIZE_16_64BIT (4 << 1) #define BLM_RX_NO_SWAP (1 << 4) #define BLM_TX_NO_SWAP (1 << 5) +#define TX_BURST_SIZE_4_64BIT (2 << 22) #define TX_BURST_SIZE_16_64BIT (4 << 22) #if defined(__BIG_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ - (RX_BURST_SIZE_16_64BIT | \ - TX_BURST_SIZE_16_64BIT) + (RX_BURST_SIZE_4_64BIT | \ + TX_BURST_SIZE_4_64BIT) #elif defined(__LITTLE_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ - (RX_BURST_SIZE_16_64BIT | \ - BLM_RX_NO_SWAP | \ - BLM_TX_NO_SWAP | \ - TX_BURST_SIZE_16_64BIT) + (RX_BURST_SIZE_4_64BIT | \ + BLM_RX_NO_SWAP | \ + BLM_TX_NO_SWAP | \ + TX_BURST_SIZE_4_64BIT) #else #error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined #endif -- cgit v1.2.3 From 2b448334a255d34401562229f467ffd95d8ed6ef Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 19 Jan 2009 17:17:18 -0800 Subject: mv643xx_eth: fix multicast filter programming Commit 66e63ffbc04706568d8789cbb00eaa8ddbcae648 ("mv643xx_eth: implement ->set_rx_mode()") cleaned up mv643xx_eth's multicast filter programming, but broke it as well. The non-special multicast filter table (for multicast addresses that are not of the form 01:00:5e:00:00:xx) consists of 256 hash table buckets organised as 64 32-bit words, where the 'accept' bits are in the LSB of each byte, so in bits 24 16 8 0 of each 32-bit word. The old code got this right, but the referenced commit broke this by using bits 3 2 1 0 instead. This commit fixes this up. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e2aa468d40f1..8c6979a26d61 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1596,7 +1596,7 @@ oom: entry = addr_crc(a); } - table[entry >> 2] |= 1 << (entry & 3); + table[entry >> 2] |= 1 << (8 * (entry & 3)); } for (i = 0; i < 0x100; i += 4) { -- cgit v1.2.3 From fe65e704534de5d0661ebc3466a2b9018945f694 Mon Sep 17 00:00:00 2001 From: Gabriel Paubert Date: Mon, 19 Jan 2009 17:18:09 -0800 Subject: mv643xx_eth: prevent interrupt storm on ifconfig down Contrary to what the docs say, the 'extended interrupt cause' bit in the interrupt cause register (bit 1) appears to not be maskable on at least some of the mv643xx_eth platforms, making writing zeroes to the interrupt mask register but not the extended interrupt mask register insufficient to stop interrupts from occuring. Therefore, also write zeroes to the extended interrupt mask register when shutting down the port. This fixes the interrupt storm seen on the Pegasos board when shutting down the interface. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 8c6979a26d61..5f31bbb614af 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2212,6 +2212,7 @@ static int mv643xx_eth_stop(struct net_device *dev) struct mv643xx_eth_private *mp = netdev_priv(dev); int i; + wrlp(mp, INT_MASK_EXT, 0x00000000); wrlp(mp, INT_MASK, 0x00000000); rdlp(mp, INT_MASK); -- cgit v1.2.3 From f4895b8bc83a22a36446c4aee277e1750fcc6a18 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Mon, 19 Jan 2009 13:19:30 +0000 Subject: wimax/i2400m: error paths that need to free an skb should use kfree_skb() Roel Kluin reported a bug in two error paths where skbs were wrongly being freed using kfree(). He provided a fix where it was replaced to kfree_skb(), as it should be. However, in i2400mu_rx(), the error path was missing returning an indication of the failure. Changed to reset rx_skb to NULL and return it to the caller, i2400mu_rxd(). It will be treated as a transient error and just ignore the packet. Depending on the buffering conditions inside the device, the data packet might be dropped or the device will signal the host again for data-ready-to-read and the host will retry. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/control.c | 2 +- drivers/net/wimax/i2400m/usb-rx.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index d3d37fed6893..15d9f51b292c 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -609,7 +609,7 @@ void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code) spin_lock_irqsave(&i2400m->rx_lock, flags); ack_skb = i2400m->ack_skb; if (ack_skb && !IS_ERR(ack_skb)) - kfree(ack_skb); + kfree_skb(ack_skb); i2400m->ack_skb = ERR_PTR(code); spin_unlock_irqrestore(&i2400m->rx_lock, flags); } diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c index 074cc1f89853..a314799967cf 100644 --- a/drivers/net/wimax/i2400m/usb-rx.c +++ b/drivers/net/wimax/i2400m/usb-rx.c @@ -184,6 +184,8 @@ void i2400mu_rx_size_maybe_shrink(struct i2400mu *i2400mu) * NOTE: this function might realloc the skb (if it is too small), * so always update with the one returned. * ERR_PTR() is < 0 on error. + * Will return NULL if it cannot reallocate -- this can be + * considered a transient retryable error. */ static struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) @@ -243,8 +245,8 @@ retry: if (printk_ratelimit()) dev_err(dev, "RX: Can't reallocate skb to %d; " "RX dropped\n", rx_size); - kfree(rx_skb); - result = 0; + kfree_skb(rx_skb); + rx_skb = NULL; goto out; /* drop it...*/ } kfree_skb(rx_skb); @@ -344,7 +346,8 @@ int i2400mu_rxd(void *_i2400mu) if (IS_ERR(rx_skb)) goto out; atomic_dec(&i2400mu->rx_pending_count); - if (rx_skb->len == 0) { /* some ignorable condition */ + if (rx_skb == NULL || rx_skb->len == 0) { + /* some "ignorable" condition */ kfree_skb(rx_skb); continue; } -- cgit v1.2.3 From e3fd553468738e0342cbd82a63ede00c983a0eb4 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Sat, 17 Jan 2009 08:27:19 +0000 Subject: myri10ge: don't forget pci_disable_device() Don't forget to call pci_disable_device() in myri10ge_remove() and when myri10ge_probe() fails. By the way, update the copyright years. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 6bb71b687f7b..e9c1296b267e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1,7 +1,7 @@ /************************************************************************* * myri10ge.c: Myricom Myri-10G Ethernet driver. * - * Copyright (C) 2005 - 2007 Myricom, Inc. + * Copyright (C) 2005 - 2009 Myricom, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.4-1.398" +#define MYRI10GE_VERSION_STR "1.4.4-1.401" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -3786,7 +3786,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (status != 0) { dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n", status); - goto abort_with_netdev; + goto abort_with_enabled; } pci_set_master(pdev); @@ -3801,13 +3801,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } if (status != 0) { dev_err(&pdev->dev, "Error %d setting DMA mask\n", status); - goto abort_with_netdev; + goto abort_with_enabled; } (void)pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd), &mgp->cmd_bus, GFP_KERNEL); if (mgp->cmd == NULL) - goto abort_with_netdev; + goto abort_with_enabled; mgp->board_span = pci_resource_len(pdev, 0); mgp->iomem_base = pci_resource_start(pdev, 0); @@ -3943,8 +3943,10 @@ abort_with_mtrr: dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), mgp->cmd, mgp->cmd_bus); -abort_with_netdev: +abort_with_enabled: + pci_disable_device(pdev); +abort_with_netdev: free_netdev(netdev); return status; } @@ -3990,6 +3992,7 @@ static void myri10ge_remove(struct pci_dev *pdev) mgp->cmd, mgp->cmd_bus); free_netdev(netdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } -- cgit v1.2.3 From 0d1cfd20cc5f785d5345d249d4b6a6f84b29e6a6 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Sat, 17 Jan 2009 11:14:31 +0000 Subject: via-velocity: fix hot spin while(--j >= 0) keeps spinning when j is unsigned: Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index a75f91dc3153..c5691fdb7079 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1302,7 +1302,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr) static int velocity_init_td_ring(struct velocity_info *vptr) { dma_addr_t curr; - unsigned int j; + int j; /* Init the TD ring entries */ for (j = 0; j < vptr->tx.numq; j++) { -- cgit v1.2.3 From 0b491eee46012772cbf029450d123e933c2e7940 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 21 Jan 2009 12:35:43 -0800 Subject: usbnet: allow type check of devdbg arguments in non-debug build Improve usbnet's devdbg to always type-check diagnostic arguments, like dev_dbg (device.h). This makes no change to the resulting size of usbnet modules. This patch also removes an #ifdef DEBUG directive from rndis_wlan so it's devdbg statements are always type-checked at compile time. Signed-off-by: Steve Glendinning Signed-off-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/wireless/rndis_wlan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 607ce9f61b54..ed93ac41297f 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1649,9 +1649,7 @@ static char *rndis_translate_scan(struct net_device *dev, char *end_buf, struct ndis_80211_bssid_ex *bssid) { -#ifdef DEBUG struct usbnet *usbdev = netdev_priv(dev); -#endif u8 *ie; char *current_val; int bssid_len, ie_len, i; -- cgit v1.2.3 From 6d317482944250228255bcbe97a95b7e7ad9a538 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 21 Jan 2009 12:56:24 -0800 Subject: usb/mcs7830: Don't use buffers from stack for USB transfers mcs7830_set_reg() and mcs7830_get_reg() are called with buffers from stack which must not be used directly for USB transfers. This causes corruption of the stack particulary on non x86 architectures because DMA may be used for these transfers. Signed-off-by: Christian Eggers Acked-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 5385d66b306e..ced8f36ebd01 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -94,10 +94,18 @@ static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) { struct usb_device *xdev = dev->udev; int ret; + void *buffer; + + buffer = kmalloc(size, GFP_NOIO); + if (buffer == NULL) + return -ENOMEM; ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ, - MCS7830_RD_BMREQ, 0x0000, index, data, + MCS7830_RD_BMREQ, 0x0000, index, buffer, size, MCS7830_CTRL_TIMEOUT); + memcpy(data, buffer, size); + kfree(buffer); + return ret; } @@ -105,10 +113,18 @@ static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data) { struct usb_device *xdev = dev->udev; int ret; + void *buffer; + + buffer = kmalloc(size, GFP_NOIO); + if (buffer == NULL) + return -ENOMEM; + + memcpy(buffer, data, size); ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ, - MCS7830_WR_BMREQ, 0x0000, index, data, + MCS7830_WR_BMREQ, 0x0000, index, buffer, size, MCS7830_CTRL_TIMEOUT); + kfree(buffer); return ret; } -- cgit v1.2.3 From 7fe99c4e28ab54eada8aa456b417114e6ef21587 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Tue, 20 Jan 2009 20:26:46 +0300 Subject: orinoco: move kmalloc(..., GFP_KERNEL) outside spinlock in orinoco_ioctl_set_genie [ 56.923623] BUG: sleeping function called from invalid context at /home/bor/src/linux-git/mm/slub.c:1599 [ 56.923644] in_atomic(): 0, irqs_disabled(): 1, pid: 3031, name: wpa_supplicant [ 56.923656] 2 locks held by wpa_supplicant/3031: [ 56.923662] #0: (rtnl_mutex){--..}, at: [] rtnl_lock+0xf/0x20 [ 56.923703] #1: (&priv->lock){++..}, at: [] orinoco_ioctl_set_genie+0x52/0x130 [orinoco] [ 56.923782] irq event stamp: 910 [ 56.923788] hardirqs last enabled at (909): [] __kmalloc+0x7b/0x140 [ 56.923820] hardirqs last disabled at (910): [] _spin_lock_irqsave+0x19/0x80 [ 56.923847] softirqs last enabled at (880): [] __do_softirq+0xc4/0x110 [ 56.923865] softirqs last disabled at (871): [] do_softirq+0x8e/0xe0 [ 56.923895] Pid: 3031, comm: wpa_supplicant Not tainted 2.6.29-rc2-1avb #1 [ 56.923905] Call Trace: [ 56.923919] [] ? do_softirq+0x8e/0xe0 [ 56.923941] [] __might_sleep+0xd2/0x100 [ 56.923952] [] __kmalloc+0xd7/0x140 [ 56.923963] [] ? _spin_lock_irqsave+0x6a/0x80 [ 56.923981] [] ? orinoco_ioctl_set_genie+0x79/0x130 [orinoco] [ 56.923999] [] ? orinoco_ioctl_set_genie+0x52/0x130 [orinoco] [ 56.924017] [] orinoco_ioctl_set_genie+0x79/0x130 [orinoco] [ 56.924036] [] ? copy_from_user+0x35/0x130 [ 56.924061] [] ioctl_standard_call+0x196/0x380 [ 56.924085] [] ? __dev_get_by_name+0x85/0xb0 [ 56.924096] [] wext_handle_ioctl+0x14f/0x230 [ 56.924113] [] ? orinoco_ioctl_set_genie+0x0/0x130 [orinoco] [ 56.924132] [] dev_ioctl+0x495/0x570 [ 56.924155] [] ? sys_sendto+0xa5/0xd0 [ 56.924171] [] ? mark_held_locks+0x48/0x90 [ 56.924183] [] ? sock_ioctl+0x0/0x280 [ 56.924193] [] sock_ioctl+0xfd/0x280 [ 56.924203] [] ? sock_ioctl+0x0/0x280 [ 56.924235] [] vfs_ioctl+0x20/0x80 [ 56.924246] [] do_vfs_ioctl+0x72/0x570 [ 56.924257] [] ? sys_send+0x32/0x40 [ 56.924268] [] ? sys_socketcall+0x1d0/0x2a0 [ 56.924280] [] ? sysenter_exit+0xf/0x16 [ 56.924292] [] sys_ioctl+0x39/0x70 [ 56.924302] [] sysenter_do_call+0x12/0x31 Signed-off-by: Andrey Borzenkov Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index c3bb85e0251e..39eab39b065f 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -5068,33 +5068,30 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, struct orinoco_private *priv = netdev_priv(dev); u8 *buf; unsigned long flags; - int err = 0; /* cut off at IEEE80211_MAX_DATA_LEN */ if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) || (wrqu->data.length && (extra == NULL))) return -EINVAL; - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - if (wrqu->data.length) { buf = kmalloc(wrqu->data.length, GFP_KERNEL); - if (buf == NULL) { - err = -ENOMEM; - goto out; - } + if (buf == NULL) + return -ENOMEM; memcpy(buf, extra, wrqu->data.length); - kfree(priv->wpa_ie); - priv->wpa_ie = buf; - priv->wpa_ie_len = wrqu->data.length; - } else { - kfree(priv->wpa_ie); - priv->wpa_ie = NULL; - priv->wpa_ie_len = 0; + } else + buf = NULL; + + if (orinoco_lock(priv, &flags) != 0) { + kfree(buf); + return -EBUSY; } + kfree(priv->wpa_ie); + priv->wpa_ie = buf; + priv->wpa_ie_len = wrqu->data.length; + if (priv->wpa_ie) { /* Looks like wl_lkm wants to check the auth alg, and * somehow pass it to the firmware. @@ -5103,9 +5100,8 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, */ } -out: orinoco_unlock(priv, &flags); - return err; + return 0; } static int orinoco_ioctl_get_genie(struct net_device *dev, -- cgit v1.2.3 From 7490889c105764d80af58dee5983d91a84e4aec8 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 18 Jan 2009 20:15:24 +0100 Subject: rt2x00: Fix TX rate short preamble detection Mac80211 provides 2 structures to handle bitrates, namely ieee80211_rate and ieee80211_tx_rate. To determine the short preamble mode for an outgoing frame, the flag IEEE80211_TX_RC_USE_SHORT_PREAMBLE must be checked on ieee80211_tx_rate and not ieee80211_rate (which rt2x00 did). This fixes a regression which was triggered in 2.6.29-rcX as reported by Chris Clayton. Signed-off-by: Ivo van Doorn Tested-By: Chris Clayton Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 746a8f36b931..0709decec9c2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -154,6 +154,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; struct ieee80211_rate *rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); const struct rt2x00_rate *hwrate; @@ -313,7 +314,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) txdesc->signal |= 0x08; } } -- cgit v1.2.3 From 11eaea416716deebcb18383b201ba8033cbf33dc Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sun, 18 Jan 2009 23:20:58 -0500 Subject: orinoco: use KERN_DEBUG for link status messages KERN_INFO is too "loud" for messages that are generated by the ordinary events, such as accociation. Use of KERN_DEBUG is consistent with mac80211. Suggested by Michael Gilbert Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 39eab39b065f..45a04faa7818 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1673,7 +1673,7 @@ static void print_linkstatus(struct net_device *dev, u16 status) s = "UNKNOWN"; } - printk(KERN_INFO "%s: New link status: %s (%04x)\n", + printk(KERN_DEBUG "%s: New link status: %s (%04x)\n", dev->name, s, status); } -- cgit v1.2.3 From 40ab73cc6c38ce93253fe8c2d7e502c948adfd13 Mon Sep 17 00:00:00 2001 From: Chr Date: Mon, 19 Jan 2009 14:30:26 +0100 Subject: p54: add missing break in eeprom parser This patch fixes a obvious memory leak in the eeprom parser. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 12d0717c3992..61b01930d9aa 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -451,8 +451,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) } if (err) goto err; - - } + } + break; case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); if (!priv->iq_autocal) { -- cgit v1.2.3 From 12da401e0d616f738c8b8a368d1f63f365cc78e4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 19 Jan 2009 16:08:48 +0100 Subject: p54: more cryptographic accelerator fixes If we let the firmware do the data encryption, we have to remove the ICV and (M)MIC at the end of the frame before we can give it back to mac80211. Or, these data frames have a few trailing bytes on cooked monitor interfaces. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 61b01930d9aa..34561e6e816b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -745,7 +745,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct p54_hdr *entry_hdr; struct p54_tx_data *entry_data; - int pad = 0; + unsigned int pad = 0, frame_len; range = (void *)info->rate_driver_data; if (range->start_addr != addr) { @@ -768,6 +768,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); + frame_len = entry->len; entry_hdr = (struct p54_hdr *) entry->data; entry_data = (struct p54_tx_data *) entry_hdr->data; priv->tx_stats[entry_data->hw_queue].len--; @@ -814,15 +815,28 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) info->status.ack_signal = p54_rssi_to_dbm(dev, (int)payload->ack_rssi); - if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { + /* Undo all changes to the frame. */ + switch (entry_data->key_type) { + case P54_CRYPTO_TKIPMICHAEL: { u8 *iv = (u8 *)(entry_data->align + pad + - entry_data->crypt_offset); + entry_data->crypt_offset); /* Restore the original TKIP IV. */ iv[2] = iv[0]; iv[0] = iv[1]; iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ + + frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */ + break; + } + case P54_CRYPTO_AESCCMP: + frame_len -= 8; /* remove CCMP_MIC */ + break; + case P54_CRYPTO_WEP: + frame_len -= 4; /* remove WEP_ICV */ + break; } + skb_trim(entry, frame_len); skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); ieee80211_tx_status_irqsafe(dev, entry); goto out; -- cgit v1.2.3 From e2fe154e918276e900067a9d1d3a6a963faee041 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 20 Jan 2009 00:27:57 +0100 Subject: p54usb: fix nasty use after free In theory, the firmware acks the received a data frame, before signaling the driver to free it again. However Artur Skawina has shown that it can happen in reverse order as well. This is very bad and could lead to memory corruptions, oopses and panics. Thanks to Artur Skawina for reporting and debugging this issue. Signed-off-by: Christian Lamparter Tested-by: Artur Skawina Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 6a6a72f6f82c..4487cc5c928b 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -144,11 +144,8 @@ static void p54u_tx_cb(struct urb *urb) struct sk_buff *skb = urb->context; struct ieee80211_hw *dev = (struct ieee80211_hw *) usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - struct p54u_priv *priv = dev->priv; - skb_pull(skb, priv->common.tx_hdr_len); - if (FREE_AFTER_TX(skb)) - p54_free_skb(dev, skb); + p54_free_skb(dev, skb); } static void p54u_tx_dummy_cb(struct urb *urb) { } @@ -230,7 +227,8 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) p54u_tx_dummy_cb, dev); usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + skb->data, skb->len, FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); usb_anchor_urb(addr_urb, &priv->submitted); err = usb_submit_urb(addr_urb, GFP_ATOMIC); @@ -269,28 +267,24 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) { struct p54u_priv *priv = dev->priv; struct urb *data_urb; - struct lm87_tx_hdr *hdr; - __le32 checksum; - __le32 addr = ((struct p54_hdr *)skb->data)->req_id; + struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); data_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!data_urb) return; - checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); - hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->chksum = checksum; - hdr->device_addr = addr; + hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); + hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(data_urb, &priv->submitted); if (usb_submit_urb(data_urb, GFP_ATOMIC)) { usb_unanchor_urb(data_urb); - skb_pull(skb, sizeof(*hdr)); p54_free_skb(dev, skb); } usb_free_urb(data_urb); @@ -300,11 +294,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) { struct p54u_priv *priv = dev->priv; struct urb *int_urb, *data_urb; - struct net2280_tx_hdr *hdr; + struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); struct net2280_reg_write *reg; int err = 0; - __le32 addr = ((struct p54_hdr *) skb->data)->req_id; - __le16 len = cpu_to_le16(skb->len); reg = kmalloc(sizeof(*reg), GFP_ATOMIC); if (!reg) @@ -327,10 +319,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) reg->addr = cpu_to_le32(P54U_DEV_BASE); reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); - hdr = (void *)skb_push(skb, sizeof(*hdr)); memset(hdr, 0, sizeof(*hdr)); - hdr->len = len; - hdr->device_addr = addr; + hdr->len = cpu_to_le16(skb->len); + hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id; usb_fill_bulk_urb(int_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), @@ -345,7 +336,8 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, p54u_tx_cb, skb); + hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? + p54u_tx_cb : p54u_tx_dummy_cb, skb); usb_anchor_urb(int_urb, &priv->submitted); err = usb_submit_urb(int_urb, GFP_ATOMIC); -- cgit v1.2.3 From de2624966f9bc6ffafc4fd6555336fabc2854420 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Mon, 19 Jan 2009 23:39:09 +0000 Subject: zd1211rw: adding Sitecom WL-603 (0df6:0036) to the USB id list Giuseppe Cala (The second "a" in "Cala" should be a grave, U+00E0) reported success on zd1211-devs@lists.sourceforge.net. The chip info is: zd1211b chip 0df6:0036 v4810 high 00-0c-f6 AL2230_RF pa0 g--N- The Sitecom WL-603 is detected as a zd1211b with a AL2230 RF transceiver chip. Signed-off-by: Giuseppe Cala Signed-off-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index b5db57d2fcf5..17527f765b39 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -84,6 +84,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, -- cgit v1.2.3 From 637f883739b32746889a191f282c9ea2590ecf4f Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 19 Jan 2009 15:30:32 -0800 Subject: iwlwifi: return NETDEV_TX_OK from _tx ops be consistent with mac80211 drivers and return correct return code. NETDEV_TX_OK is 0, but we need to be consistent wrt formatting amongst implementations re: http://marc.info/?l=linux-wireless&m=123119327419865&w=2 Signed-off-by: Reinette Chatre Reviewed-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5da6b35cd26d..0dc8eed16404 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2482,7 +2482,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); IWL_DEBUG_MACDUMP("leave\n"); - return 0; + return NETDEV_TX_OK; } static int iwl_mac_add_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 15f5655c636e..95d01984c80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6538,7 +6538,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); IWL_DEBUG_MAC80211("leave\n"); - return 0; + return NETDEV_TX_OK; } static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, -- cgit v1.2.3 From 81f75bbf67c7a26ea1266ac93b9319bb985d588d Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:31 +0000 Subject: bnx2x: Reset HW before use To avoid complications, make sure that the HW is in reset (as it should be) before trying to take it out of reset. In normal flows, the HW is indeed in rest so this should have no effect Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 074374ff93f3..ed8b34665931 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -5148,12 +5148,21 @@ static void enable_blocks_attention(struct bnx2x *bp) } +static void bnx2x_reset_common(struct bnx2x *bp) +{ + /* reset_common */ + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, + 0xd3ffff7f); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); +} + static int bnx2x_init_common(struct bnx2x *bp) { u32 val, i; DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp)); + bnx2x_reset_common(bp); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); @@ -6640,14 +6649,6 @@ static void bnx2x_reset_port(struct bnx2x *bp) /* TODO: Close Doorbell port? */ } -static void bnx2x_reset_common(struct bnx2x *bp) -{ - /* reset_common */ - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, - 0xd3ffff7f); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403); -} - static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) { DP(BNX2X_MSG_MCP, "function %d reset_code %x\n", -- cgit v1.2.3 From e94d8af3da79f4bfbd22819d28ecf0602456f06f Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:36 +0000 Subject: bnx2x: Disable napi Calling napi disabled unconditionally at netif stop Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ed8b34665931..860b9f8ddd30 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6143,8 +6143,8 @@ static void bnx2x_netif_start(struct bnx2x *bp) static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) { bnx2x_int_disable_sync(bp, disable_hw); + bnx2x_napi_disable(bp); if (netif_running(bp->dev)) { - bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); bp->dev->trans_start = jiffies; /* prevent tx timeout */ } @@ -6689,8 +6689,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_set_storm_rx_mode(bp); bnx2x_netif_stop(bp, 1); - if (!netif_running(bp->dev)) - bnx2x_napi_disable(bp); + del_timer_sync(&bp->timer); SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); -- cgit v1.2.3 From 2dfe0e1fecb582b4aae7f2490904864c05472f3a Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:44 +0000 Subject: bnx2x: Handling load failures Failures on load were not handled correctly - separate the flow to handle different failures Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 154 +++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 66 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 860b9f8ddd30..707c4bbe46a4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6328,7 +6328,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev); static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { u32 load_code; - int i, rc; + int i, rc = 0; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -6336,48 +6336,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; - /* Send LOAD_REQUEST command to MCP - Returns the type of LOAD command: - if it is the first port to be initialized - common blocks should be initialized, otherwise - not - */ - if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); - if (!load_code) { - BNX2X_ERR("MCP response failure, aborting\n"); - return -EBUSY; - } - if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) - return -EBUSY; /* other port in diagnostic mode */ - - } else { - int port = BP_PORT(bp); - - DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - load_count[0]++; - load_count[1 + port]++; - DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - if (load_count[0] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_COMMON; - else if (load_count[1 + port] == 1) - load_code = FW_MSG_CODE_DRV_LOAD_PORT; - else - load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; - } - - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || - (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) - bp->port.pmf = 1; - else - bp->port.pmf = 0; - DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); - - /* if we can't use MSI-X we only need one fp, - * so try to enable MSI-X with the requested number of fp's - * and fallback to inta with one fp - */ if (use_inta) { bp->num_queues = 1; @@ -6392,7 +6350,15 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) else bp->num_queues = 1; - if (bnx2x_enable_msix(bp)) { + DP(NETIF_MSG_IFUP, + "set number of queues to %d\n", bp->num_queues); + + /* if we can't use MSI-X we only need one fp, + * so try to enable MSI-X with the requested number of fp's + * and fallback to MSI or legacy INTx with one fp + */ + rc = bnx2x_enable_msix(bp); + if (rc) { /* failed to enable MSI-X */ bp->num_queues = 1; if (use_multi) @@ -6400,8 +6366,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) " to enable MSI-X\n"); } } - DP(NETIF_MSG_IFUP, - "set number of queues to %d\n", bp->num_queues); if (bnx2x_alloc_mem(bp)) return -ENOMEM; @@ -6410,30 +6374,85 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_fp(bp, i, disable_tpa) = ((bp->flags & TPA_ENABLE_FLAG) == 0); + for_each_queue(bp, i) + netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), + bnx2x_poll, 128); + +#ifdef BNX2X_STOP_ON_ERROR + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + fp->poll_no_work = 0; + fp->poll_calls = 0; + fp->poll_max_calls = 0; + fp->poll_complete = 0; + fp->poll_exit = 0; + } +#endif + bnx2x_napi_enable(bp); + if (bp->flags & USING_MSIX_FLAG) { rc = bnx2x_req_msix_irqs(bp); if (rc) { pci_disable_msix(bp->pdev); - goto load_error; + goto load_error1; } + printk(KERN_INFO PFX "%s: using MSI-X\n", bp->dev->name); } else { bnx2x_ack_int(bp); rc = bnx2x_req_irq(bp); if (rc) { - BNX2X_ERR("IRQ request failed, aborting\n"); - goto load_error; + BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); + goto load_error1; } } - for_each_queue(bp, i) - netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), - bnx2x_poll, 128); + /* Send LOAD_REQUEST command to MCP + Returns the type of LOAD command: + if it is the first port to be initialized + common blocks should be initialized, otherwise - not + */ + if (!BP_NOMCP(bp)) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EBUSY; + goto load_error2; + } + if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { + rc = -EBUSY; /* other port in diagnostic mode */ + goto load_error2; + } + + } else { + int port = BP_PORT(bp); + + DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + load_count[0]++; + load_count[1 + port]++; + DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n", + load_count[0], load_count[1], load_count[2]); + if (load_count[0] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_COMMON; + else if (load_count[1 + port] == 1) + load_code = FW_MSG_CODE_DRV_LOAD_PORT; + else + load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; + } + + if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || + (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) + bp->port.pmf = 1; + else + bp->port.pmf = 0; + DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); /* Initialize HW */ rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); - goto load_int_disable; + goto load_error2; } /* Setup NIC internals and enable interrupts */ @@ -6445,7 +6464,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; - goto load_rings_free; + goto load_error3; } } @@ -6454,7 +6473,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1H(bp)) @@ -6467,7 +6486,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) for_each_nondefault_queue(bp, i) { rc = bnx2x_setup_multi(bp, i); if (rc) - goto load_netif_stop; + goto load_error3; } if (CHIP_IS_E1(bp)) @@ -6483,18 +6502,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) case LOAD_NORMAL: /* Tx queue should be only reenabled */ netif_wake_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); break; case LOAD_OPEN: netif_start_queue(bp->dev); + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); - if (bp->flags & USING_MSIX_FLAG) - printk(KERN_INFO PFX "%s: using MSI-X\n", - bp->dev->name); break; case LOAD_DIAG: + /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); bp->state = BNX2X_STATE_DIAG; break; @@ -6512,20 +6531,23 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; -load_netif_stop: - bnx2x_napi_disable(bp); -load_rings_free: +load_error3: + bnx2x_int_disable_sync(bp, 1); + if (!BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + } + bp->port.pmf = 0; /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); -load_int_disable: - bnx2x_int_disable_sync(bp, 1); +load_error2: /* Release IRQs */ bnx2x_free_irq(bp); -load_error: +load_error1: + bnx2x_napi_disable(bp); bnx2x_free_mem(bp); - bp->port.pmf = 0; /* TBD we really need to reset the chip if we want to recover from this */ -- cgit v1.2.3 From 6eccabb301d442e6106ecc84b07a976c2816d9fb Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 03:37:48 +0000 Subject: bnx2x: Carrier off first call Call carrier off should not be called after register_netdev since after register netdev open can be called at any time followed by an interrupt that will set it to carrier_on and the probe will resume control and set it to off Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 707c4bbe46a4..fbd71659cca6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9827,6 +9827,8 @@ static int bnx2x_open(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + netif_carrier_off(dev); + bnx2x_set_power_state(bp, PCI_D0); return bnx2x_nic_load(bp, LOAD_OPEN); @@ -10332,8 +10334,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, goto init_one_exit; } - netif_carrier_off(dev); - bp->common.name = board_info[ent->driver_data].name; printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," " IRQ %d, ", dev->name, bp->common.name, -- cgit v1.2.3 From 7cde1c8b79f913a0158bae4f4c612de2cb98e7e4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:25 +0000 Subject: bnx2x: Calling napi_del rmmod might hang without this patch since the reference counter is not going down Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fbd71659cca6..71fbf2dbda3b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6547,6 +6547,8 @@ load_error2: bnx2x_free_irq(bp); load_error1: bnx2x_napi_disable(bp); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); /* TBD we really need to reset the chip @@ -6855,6 +6857,8 @@ unload_error: bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; @@ -10481,6 +10485,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + for_each_queue(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; -- cgit v1.2.3 From 5650d9d4cbf3898d3f9725ccad5dfca6bc086324 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:29 +0000 Subject: bnx2x: Missing rmb when waiting for FW response Waiting for the FW to response requires a memory barrier Signed-off-by: Michal Kalderon Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 71fbf2dbda3b..f71b8a5872b3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6622,6 +6622,7 @@ static int bnx2x_stop_leading(struct bnx2x *bp) } cnt--; msleep(1); + rmb(); /* Refresh the dsb_sp_prod */ } bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; bp->fp[0].state = BNX2X_FP_STATE_CLOSED; -- cgit v1.2.3 From 3910c8ae44c59cebed721e33aa496f0a385b4e03 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:32 +0000 Subject: bnx2x: loopback test failure A link change interrupt might be queued and activated after the loopback was set and it will cause the loopback to fail. The PHY lock should be kept until the loopback test is over. That implies that the bnx2x_test_link should used within the loopback function and not bnx2x_wait_for_link since that function also takes the PHY link Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f71b8a5872b3..d95714f780f3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8750,18 +8750,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) if (loopback_mode == BNX2X_MAC_LOOPBACK) { bp->link_params.loopback_mode = LOOPBACK_BMAC; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); } else if (loopback_mode == BNX2X_PHY_LOOPBACK) { + u16 cnt = 1000; bp->link_params.loopback_mode = LOOPBACK_XGXS_10; - bnx2x_acquire_phy_lock(bp); bnx2x_phy_init(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); /* wait until link state is restored */ - bnx2x_wait_for_link(bp, link_up); - + if (link_up) + while (cnt-- && bnx2x_test_link(&bp->link_params, + &bp->link_vars)) + msleep(10); } else return -EINVAL; @@ -8867,6 +8866,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) return BNX2X_LOOPBACK_FAILED; bnx2x_netif_stop(bp, 1); + bnx2x_acquire_phy_lock(bp); if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) { DP(NETIF_MSG_PROBE, "MAC loopback failed\n"); @@ -8878,6 +8878,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up) rc |= BNX2X_PHY_LOOPBACK_FAILED; } + bnx2x_release_phy_lock(bp); bnx2x_netif_start(bp); return rc; -- cgit v1.2.3 From 5422a2257350d984094e655b2361abed51a9ddc1 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Thu, 22 Jan 2009 06:01:37 +0000 Subject: bnx2x: Version Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d95714f780f3..4b84f6ce5ed2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.24" -#define DRV_MODULE_RELDATE "2009/01/14" +#define DRV_MODULE_VERSION "1.45.25" +#define DRV_MODULE_RELDATE "2009/01/22" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ -- cgit v1.2.3 From 6f051069d8a2045666055e3020ae8a7dec9762e0 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 22 Jan 2009 13:51:24 -0800 Subject: phylib: Fix oops in suspend/resume paths Suspend/resume routines check for phydrv != NULL, but that is wrong because "phydrv" comes from container_of(drv). If drv is NULL, then container_of(drv) will return non-NULL result, and the checks won't work. The Freescale TBI PHYs are driver-less, so "drv" is NULL, and that leads to the following oops: Unable to handle kernel paging request for data at address 0xffffffe4 Faulting instruction address: 0xc0215554 Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c0215554] mdio_bus_suspend+0x34/0x70 LR [c01cc508] suspend_device+0x258/0x2bc Call Trace: [cfad3da0] [cfad3db8] 0xcfad3db8 (unreliable) [cfad3db0] [c01cc508] suspend_device+0x258/0x2bc [cfad3dd0] [c01cc62c] dpm_suspend+0xc0/0x140 [cfad3e20] [c01cc6f4] device_suspend+0x48/0x5c [cfad3e40] [c0068dd8] suspend_devices_and_enter+0x8c/0x148 [cfad3e60] [c00690f8] enter_state+0x100/0x118 [cfad3e80] [c00691c0] state_store+0xb0/0xe4 [cfad3ea0] [c018c938] kobj_attr_store+0x24/0x3c [cfad3eb0] [c00ea9a8] flush_write_buffer+0x58/0x7c [cfad3ed0] [c00eadf0] sysfs_write_file+0x58/0xa0 [cfad3ef0] [c009e810] vfs_write+0xb4/0x16c [cfad3f10] [c009ed40] sys_write+0x4c/0x90 [cfad3f40] [c0014954] ret_from_syscall+0x0/0x38 [...] This patch fixes the issue, plus removes unneeded parentheses and fixes indentation level in mdio_bus_suspend(). Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 11adf6ed4628..811a637695ca 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -296,9 +296,8 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state) struct phy_driver *phydrv = to_phy_driver(drv); struct phy_device *phydev = to_phy_device(dev); - if ((!device_may_wakeup(phydev->dev.parent)) && - (phydrv && phydrv->suspend)) - ret = phydrv->suspend(phydev); + if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent)) + ret = phydrv->suspend(phydev); return ret; } @@ -310,8 +309,7 @@ static int mdio_bus_resume(struct device * dev) struct phy_driver *phydrv = to_phy_driver(drv); struct phy_device *phydev = to_phy_device(dev); - if ((!device_may_wakeup(phydev->dev.parent)) && - (phydrv && phydrv->resume)) + if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent)) ret = phydrv->resume(phydev); return ret; -- cgit v1.2.3 From c64d2a9afbccd0aecb122d108770a407fe7b7e3f Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 22 Jan 2009 14:07:43 -0800 Subject: phy: Add suspend/resume support to SMSC PHYs All supported SMSC PHYs implement the standard "power down" bit 11 of BMCR, so this patch adds support using the generic genphy_{suspend,resume} functions. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index c05d38d46350..1387187543e4 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -81,6 +81,9 @@ static struct phy_driver lan83c185_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -102,6 +105,9 @@ static struct phy_driver lan8187_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -123,6 +129,9 @@ static struct phy_driver lan8700_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; @@ -144,6 +153,9 @@ static struct phy_driver lan911x_int_driver = { .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE, } }; -- cgit v1.2.3 From b4068a80492022848c11123bf485aff5c902c583 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 20 Jan 2009 23:11:21 +0100 Subject: p54usb: fix packet loss with first generation devices Artur Skawina confirmed that the first generation devices needs the same URB_ZERO_PACKET flag, in oder to finish the pending transfer properly. The second generation has been successfully fixed by "p54usb: fix random traffic stalls (LM87)" (43af18f06d5) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 4487cc5c928b..5de2ebfb28c7 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -229,6 +229,8 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), skb->data, skb->len, FREE_AFTER_TX(skb) ? p54u_tx_cb : p54u_tx_dummy_cb, skb); + addr_urb->transfer_flags |= URB_ZERO_PACKET; + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(addr_urb, &priv->submitted); err = usb_submit_urb(addr_urb, GFP_ATOMIC); @@ -237,7 +239,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) goto out; } - usb_anchor_urb(addr_urb, &priv->submitted); + usb_anchor_urb(data_urb, &priv->submitted); err = usb_submit_urb(data_urb, GFP_ATOMIC); if (err) usb_unanchor_urb(data_urb); @@ -332,12 +334,13 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) * free what's inside the transfer_buffer after the callback routine * has completed. */ - int_urb->transfer_flags |= URB_FREE_BUFFER; + int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET; usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? p54u_tx_cb : p54u_tx_dummy_cb, skb); + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(int_urb, &priv->submitted); err = usb_submit_urb(int_urb, GFP_ATOMIC); -- cgit v1.2.3 From c338ba3ca5bef2df2082d9e8d336ff7b2880c326 Mon Sep 17 00:00:00 2001 From: "Abbas, Mohamed" Date: Wed, 21 Jan 2009 10:58:02 -0800 Subject: iwlwifi: fix rs_get_rate WARN_ON() In ieee80211_sta structure there is u64 supp_rates[IEEE80211_NUM_BANDS] this is filled with all support rate from assoc_resp. If we associate with G-band AP only supp_rates of G-band will be set the other band supp_rates will be set to 0. If the user type this command this will cause mac80211 to set to new channel, mac80211 does not disassociate in setting new channel, so the active band is now A-band. then in handling the new essid mac80211 will kick in the assoc steps which involve sending disassociation frame. in this mac80211 will WARN_ON sta->supp_rates[A_BAND] == 0. This fixes: http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1822 http://www.kerneloops.org/searchweek.php?search=rs_get_rate Signed-off-by: mohamed abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 14 +++++++++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 9b60a0c5de5f..21c841847d88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, s8 scale_action = 0; unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc, rate_mask; + u16 fc; + u16 rate_mask = 0; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); + if (sta) + rate_mask = sta->supp_rates[sband->band]; + /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); @@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (!rate_mask) + info->control.rates[0].idx = + rate_lowest_index(sband, NULL); + else + info->control.rates[0].idx = + rate_lowest_index(sband, sta); return; } - rate_mask = sta->supp_rates[sband->band]; index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f3f17929ca0b..27f50471aed8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -944,7 +944,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, } /* See if there's a better rate or modulation mode to try. */ - rs_rate_scale_perform(priv, hdr, sta, lq_sta); + if (sta && sta->supp_rates[sband->band]) + rs_rate_scale_perform(priv, hdr, sta, lq_sta); out: return; } @@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; + u64 mask_bit = 0; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); + if (sta) + mask_bit = sta->supp_rates[sband->band]; + /* Send management frames and broadcast/multicast data using lowest * rate. */ if (!ieee80211_is_data(hdr->frame_control) || is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { - info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (!mask_bit) + info->control.rates[0].idx = + rate_lowest_index(sband, NULL); + else + info->control.rates[0].idx = + rate_lowest_index(sband, sta); return; } -- cgit v1.2.3 From 2fcbab044a3faf4d4a6e269148dd1f188303b206 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 23 Jan 2009 11:46:32 -0600 Subject: rtl8187: Add termination packet to prevent stall The RTL8187 and RTL8187B devices can stall unless an explicit termination packet is sent. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 6ad6bac37706..22bc07ef2f37 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -273,6 +273,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), buf, skb->len, rtl8187_tx_cb, skb); + urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(urb, &priv->anchored); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc < 0) { -- cgit v1.2.3 From fb22d72782b023cda5e9876d3381f30932a64f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 22 Jan 2009 23:29:42 +0100 Subject: [NET] am79c961a: fix spin_lock usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spin_lock functions take a pointer to the lock, not the lock itself. This error was noticed by compiling ebsa110_defconfig for linux-rt where the locking functions obviously are more picky about their arguments. Signed-off-by: Uwe Kleine-König Cc: Roel Kluin <12o3l@tiscali.nl> Cc: Steven Rostedt Cc: netdev@vger.kernel.org Signed-off-by: Russell King --- drivers/net/arm/am79c961a.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 0c628a9e5339..c2d012fcc29b 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -208,9 +208,9 @@ am79c961_init_for_open(struct net_device *dev) /* * Stop the chip. */ - spin_lock_irqsave(priv->chip_lock, flags); + spin_lock_irqsave(&priv->chip_lock, flags); write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP); - spin_unlock_irqrestore(priv->chip_lock, flags); + spin_unlock_irqrestore(&priv->chip_lock, flags); write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */ write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */ @@ -332,10 +332,10 @@ am79c961_close(struct net_device *dev) netif_stop_queue(dev); netif_carrier_off(dev); - spin_lock_irqsave(priv->chip_lock, flags); + spin_lock_irqsave(&priv->chip_lock, flags); write_rreg (dev->base_addr, CSR0, CSR0_STOP); write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); - spin_unlock_irqrestore(priv->chip_lock, flags); + spin_unlock_irqrestore(&priv->chip_lock, flags); free_irq (dev->irq, dev); @@ -391,7 +391,7 @@ static void am79c961_setmulticastlist (struct net_device *dev) am79c961_mc_hash(dmi, multi_hash); } - spin_lock_irqsave(priv->chip_lock, flags); + spin_lock_irqsave(&priv->chip_lock, flags); stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP; @@ -405,9 +405,9 @@ static void am79c961_setmulticastlist (struct net_device *dev) * Spin waiting for chip to report suspend mode */ while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) { - spin_unlock_irqrestore(priv->chip_lock, flags); + spin_unlock_irqrestore(&priv->chip_lock, flags); nop(); - spin_lock_irqsave(priv->chip_lock, flags); + spin_lock_irqsave(&priv->chip_lock, flags); } } @@ -429,7 +429,7 @@ static void am79c961_setmulticastlist (struct net_device *dev) write_rreg(dev->base_addr, CTRL1, 0); } - spin_unlock_irqrestore(priv->chip_lock, flags); + spin_unlock_irqrestore(&priv->chip_lock, flags); } static void am79c961_timeout(struct net_device *dev) @@ -467,10 +467,10 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP); priv->txhead = head; - spin_lock_irqsave(priv->chip_lock, flags); + spin_lock_irqsave(&priv->chip_lock, flags); write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA); dev->trans_start = jiffies; - spin_unlock_irqrestore(priv->chip_lock, flags); + spin_unlock_irqrestore(&priv->chip_lock, flags); /* * If the next packet is owned by the ethernet device, -- cgit v1.2.3 From e918085aaff34086e265f825dd469926b1aec4a4 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Sun, 25 Jan 2009 18:06:26 -0800 Subject: virtio_net: Fix MAX_PACKET_LEN to support 802.1Q VLANs 802.1Q expanded the maximum ethernet frame size by 4 bytes for the VLAN tag. We're not taking this into account in virtio_net, which means the buffers we provide to the backend in the virtqueue RX ring aren't big enough to hold a full MTU VLAN packet. For QEMU/KVM, this results in the backend exiting with a packet truncation error. Signed-off-by: Alex Williamson Acked-by: Mark McLoughlin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 43f6523c40be..63ef2a8905fb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -24,6 +24,7 @@ #include #include #include +#include static int napi_weight = 128; module_param(napi_weight, int, 0444); @@ -33,7 +34,7 @@ module_param(csum, bool, 0444); module_param(gso, bool, 0444); /* FIXME: MTU in config. */ -#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN) +#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) #define GOOD_COPY_LEN 128 struct virtnet_info -- cgit v1.2.3 From 78272bbab895cc8f63bab5181dee55b72208e3b7 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 26 Jan 2009 12:16:26 -0800 Subject: e1000e: workaround hw errata There is a hardware errata in some revisions of the 82574 that needs to be worked around in the driver by setting a register bit at init. If this bit is not set A0 versions of the 82574 can generate tx hangs. Signed-off-by: Jesse Brandeburg Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 6 +++++- drivers/net/e1000e/hw.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cf43ee743b3c..0890162953e9 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -981,11 +981,15 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) ew32(PBA_ECC, reg); } - /* PCI-Ex Control Register */ + /* PCI-Ex Control Registers */ if (hw->mac.type == e1000_82574) { reg = er32(GCR); reg |= (1 << 22); ew32(GCR, reg); + + reg = er32(GCR2); + reg |= 1; + ew32(GCR2, reg); } return; diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index f25e961c6b3b..2d4ce0492df0 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -206,6 +206,7 @@ enum e1e_registers { E1000_MANC2H = 0x05860, /* Management Control To Host - RW */ E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */ E1000_GCR = 0x05B00, /* PCI-Ex Control */ + E1000_GCR2 = 0x05B64, /* PCI-Ex Control #2 */ E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ -- cgit v1.2.3 From cdff1036492ac97b4213aeab2546914a633a7de7 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 26 Jan 2009 12:34:57 -0800 Subject: netxen: fix vlan tso/checksum offload o set netdev->vlan_features appropriately. o fix tso descriptor initialization for vlan case. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index d854f07ef4d3..645d384fe87e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -735,17 +735,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - /* ScatterGather support */ - netdev->features = NETIF_F_SG; - netdev->features |= NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_TSO; + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + if (NX_IS_REVISION_P3(revision_id)) { - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO6; + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); } - if (adapter->pci_using_dac) + if (adapter->pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } /* * Set the CRB window to invalid. If any register in window 0 is @@ -1166,6 +1167,14 @@ static bool netxen_tso_check(struct net_device *netdev, { bool tso = false; u8 opcode = TX_ETHER_PKT; + __be16 protocol = skb->protocol; + u16 flags = 0; + + if (protocol == __constant_htons(ETH_P_8021Q)) { + struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; + protocol = vh->h_vlan_encapsulated_proto; + flags = FLAGS_VLAN_TAGGED; + } if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { @@ -1174,21 +1183,21 @@ static bool netxen_tso_check(struct net_device *netdev, desc->total_hdr_length = skb_transport_offset(skb) + tcp_hdrlen(skb); - opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + opcode = (protocol == __constant_htons(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (skb->protocol == htons(ETH_P_IP)) { + if (protocol == __constant_htons(ETH_P_IP)) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if(l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (skb->protocol == htons(ETH_P_IPV6)) { + } else if (protocol == __constant_htons(ETH_P_IPV6)) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) @@ -1199,7 +1208,7 @@ static bool netxen_tso_check(struct net_device *netdev, } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); - netxen_set_tx_flags_opcode(desc, 0, opcode); + netxen_set_tx_flags_opcode(desc, flags, opcode); return tso; } -- cgit v1.2.3 From 32ec803348b4d5f1353e1d7feae30880b8b3e342 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 26 Jan 2009 12:35:19 -0800 Subject: netxen: reduce memory footprint o reduce rx ring size from 8192 to 4096. o cut down old huge lro buffers. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 12 ++++++------ drivers/net/netxen/netxen_nic_ethtool.c | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index c11c568fd7db..a75a31005fd3 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -146,7 +146,7 @@ #define MAX_RX_BUFFER_LENGTH 1760 #define MAX_RX_JUMBO_BUFFER_LENGTH 8062 -#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512) +#define MAX_RX_LRO_BUFFER_LENGTH (8062) #define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2) #define RX_JUMBO_DMA_MAP_LEN \ (MAX_RX_JUMBO_BUFFER_LENGTH - 2) @@ -207,11 +207,11 @@ #define MAX_CMD_DESCRIPTORS 4096 #define MAX_RCV_DESCRIPTORS 16384 -#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4) -#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4) -#define MAX_RCV_DESCRIPTORS_10G 8192 -#define MAX_JUMBO_RCV_DESCRIPTORS 1024 -#define MAX_LRO_RCV_DESCRIPTORS 64 +#define MAX_CMD_DESCRIPTORS_HOST 1024 +#define MAX_RCV_DESCRIPTORS_1G 2048 +#define MAX_RCV_DESCRIPTORS_10G 4096 +#define MAX_JUMBO_RCV_DESCRIPTORS 512 +#define MAX_LRO_RCV_DESCRIPTORS 8 #define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS #define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS #define MAX_RCV_DESC MAX_RCV_DESCRIPTORS diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index c0bd40fcf708..0894a7be0225 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -561,7 +561,10 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) } ring->tx_pending = adapter->max_tx_desc_count; - ring->rx_max_pending = MAX_RCV_DESCRIPTORS; + if (adapter->ahw.board_type == NETXEN_NIC_GBE) + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; + else + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST; ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS; ring->rx_mini_max_pending = 0; -- cgit v1.2.3 From e8b5fc514d1c7637cb4b8f77e7d8ac33ef66130c Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 26 Jan 2009 12:36:42 -0800 Subject: bnx2x: tx_has_work should not wait for FW The current tx_has_work waited until all packets sent by the driver are marked as completed by the FW. This is too greedy and it causes the bnx2x_poll to spin in vain. The driver should only check that all packets FW already completed are freed - only in unload flow the driver should make sure that transmit queue is empty Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4b84f6ce5ed2..d3e7775a9ccf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.25" -#define DRV_MODULE_RELDATE "2009/01/22" +#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ @@ -740,8 +740,15 @@ static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp) /* Tell compiler that status block fields can change */ barrier(); tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); - return ((fp->tx_pkt_prod != tx_cons_sb) || - (fp->tx_pkt_prod != fp->tx_pkt_cons)); + return (fp->tx_pkt_cons != tx_cons_sb); +} + +static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) +{ + /* Tell compiler that consumer and producer can change */ + barrier(); + return (fp->tx_pkt_prod != fp->tx_pkt_cons); + } /* free skb in the packet ring at pos idx @@ -6729,7 +6736,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) cnt = 1000; smp_rmb(); - while (bnx2x_has_tx_work(fp)) { + while (bnx2x_has_tx_work_unload(fp)) { bnx2x_tx_int(fp, 1000); if (!cnt) { -- cgit v1.2.3 From cd1f55a5b49b74e13ed9e7bc74d005803aaa0da8 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 26 Jan 2009 14:33:23 -0800 Subject: gianfar: Revive VLAN support commit 77ecaf2d5a8bfd548eed3f05c1c2e6573d5de4ba ("gianfar: Fix VLAN HW feature related frame/buffer size calculation") wrongly removed priv->vlgrp assignment, and now priv->vlgrp is always NULL. This patch fixes the issue, plus fixes following sparse warning introduced by the same commit: gianfar.c:1406:13: warning: context imbalance in 'gfar_vlan_rx_register' - wrong count at exit gfar_vlan_rx_register() checks for "if (old_grp == grp)" and tries to return w/o dropping the lock. According to net/8021q/vlan.c VLAN core issues rx_register() callback: 1. In register_vlan_dev() only on a newly created group; 2. In unregister_vlan_dev() only if the group becomes empty. Thus the check in the gianfar driver isn't needed. Signed-off-by: Anton Vorontsov Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ea530673236e..3f7eab42aef1 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1423,15 +1423,11 @@ static void gfar_vlan_rx_register(struct net_device *dev, { struct gfar_private *priv = netdev_priv(dev); unsigned long flags; - struct vlan_group *old_grp; u32 tempval; spin_lock_irqsave(&priv->rxlock, flags); - old_grp = priv->vlgrp; - - if (old_grp == grp) - return; + priv->vlgrp = grp; if (grp) { /* Enable VLAN tag insertion */ -- cgit v1.2.3 From d4732d3c59b84bb093e11c8f755f32801b4bf86d Mon Sep 17 00:00:00 2001 From: Matt Waddel Date: Tue, 13 Jan 2009 17:13:06 +1000 Subject: m68knommu: add ColdFire M532x to the FEC configuration options Signed-off-by: Matt Waddel Signed-off-by: Greg Ungerer --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9fe8cb7d43ac..6bdfd47d679d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1829,7 +1829,7 @@ config 68360_ENET config FEC bool "FEC ethernet controller (of ColdFire CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x + depends on M523x || M527x || M5272 || M528x || M520x || M532x help Say Y here if you want to use the built-in 10/100 Fast ethernet controller on some Motorola ColdFire processors. -- cgit v1.2.3 From b9d57f94bb0ed56a5a2b58552a9ff4453013ff0b Mon Sep 17 00:00:00 2001 From: Matt Waddel Date: Tue, 13 Jan 2009 17:14:20 +1000 Subject: m68knommu: correct the mii calculations for 532x ColdFire FEC Signed-off-by: Matt Waddel Signed-off-by: Greg Ungerer --- drivers/net/fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7e33c129d51c..2769083bfe83 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1698,7 +1698,7 @@ static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_priva /* * Set MII speed to 2.5 MHz */ - fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; + fep->phy_speed = (MCF_CLK / 3) / (2500000 * 2 ) * 2; fecp->fec_mii_speed = fep->phy_speed; fec_restart(dev, 0); -- cgit v1.2.3