From abf0437b420b1476b9afd56af69d1a725f51359c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 14 Mar 2007 09:04:21 +0000 Subject: [PATCH] ibmtr probe is __devinit, not __init used by ->attach() in pcmcia analog Signed-off-by: Al Viro Acked-by: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/net/pcmcia/ibmtr_cs.c | 4 ++-- drivers/net/tokenring/ibmtr.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index a956a51d284f..1060154ae750 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -138,7 +138,7 @@ static const struct ethtool_ops netdev_ethtool_ops = { ======================================================================*/ -static int ibmtr_attach(struct pcmcia_device *link) +static int __devinit ibmtr_attach(struct pcmcia_device *link) { ibmtr_dev_t *info; struct net_device *dev; @@ -217,7 +217,7 @@ static void ibmtr_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int ibmtr_config(struct pcmcia_device *link) +static int __devinit ibmtr_config(struct pcmcia_device *link) { ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 36202e94ee91..01d55315ee8c 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -346,7 +346,7 @@ static void ibmtr_cleanup_card(struct net_device *dev) * which references it. ****************************************************************************/ -static int __init ibmtr_probe(struct net_device *dev) +static int __devinit ibmtr_probe(struct net_device *dev) { int i; int base_addr = dev->base_addr; @@ -366,7 +366,7 @@ static int __init ibmtr_probe(struct net_device *dev) return -ENODEV; } -int __init ibmtr_probe_card(struct net_device *dev) +int __devinit ibmtr_probe_card(struct net_device *dev) { int err = ibmtr_probe(dev); if (!err) { -- cgit v1.2.2 From a31e40f614788bbc07b3eb4fcf47a16299a4fe01 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 14 Mar 2007 09:18:20 +0000 Subject: [PATCH] dmfe trivial endianness annotations Signed-off-by: Al Viro Acked-by: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/net/tulip/dmfe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 24a29c99ba94..9aeac76184f3 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -190,13 +190,13 @@ /* Structure/enum declaration ------------------------------- */ struct tx_desc { - u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ + __le32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ char *tx_buf_ptr; /* Data for us */ struct tx_desc *next_tx_desc; } __attribute__(( aligned(32) )); struct rx_desc { - u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ + __le32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ struct sk_buff *rx_skb_ptr; /* Data for us */ struct rx_desc *next_rx_desc; } __attribute__(( aligned(32) )); @@ -458,7 +458,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* read 64 word srom data */ for (i = 0; i < 64; i++) - ((u16 *) db->srom)[i] = + ((__le16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i)); /* Set Node address */ -- cgit v1.2.2 From 7ccec1b94e456b01cbef7cfb1bc97e2b76f24ab5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 14 Mar 2007 09:20:10 +0000 Subject: [PATCH] atl1 trivial endianness misannotations NB: driver is choke-full of code that will break on big-endian; as long as the hardware is onboard-only we can live with that, but sooner or later that'll need fixing. Signed-off-by: Al Viro Acked-by: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/net/atl1/atl1_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index 88d4f70035bb..dee3638ad744 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -1328,7 +1328,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { cso = skb->h.raw - skb->data; - css = (skb->h.raw + skb->csum) - skb->data; + css = (skb->h.raw + skb->csum_offset) - skb->data; if (unlikely(cso & 0x1)) { printk(KERN_DEBUG "%s: payload offset != even number\n", atl1_driver_name); @@ -1562,7 +1562,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* mss will be nonzero if we're doing segment offload (TSO/GSO) */ mss = skb_shinfo(skb)->gso_size; if (mss) { - if (skb->protocol == ntohs(ETH_P_IP)) { + if (skb->protocol == htons(ETH_P_IP)) { proto_hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); if (unlikely(proto_hdr_len > len)) { -- cgit v1.2.2 From 2eb3e621c4e07e9e7200dbb66f0433b4caafb8e7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 12 Mar 2007 15:16:26 -0700 Subject: skge: set mac address bonding fix When bonding does fail over it calls set_mac_address. When this happens as the result of another port going down, the phy_mutex that is common to both ports is held, so it deadlocks. Setting the address doesn't need to do anything that needs the phy_mutex, it already has the RTNL to protect against other admin actions. This change just disables the receiver to avoid any hardware confusion while address is changing. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index eea75a401b0c..8fecf1b817f7 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3275,24 +3275,30 @@ static int skge_set_mac_address(struct net_device *dev, void *p) struct skge_hw *hw = skge->hw; unsigned port = skge->port; const struct sockaddr *addr = p; + u16 ctrl; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - mutex_lock(&hw->phy_mutex); memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_1 + port*8, - dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, - dev->dev_addr, ETH_ALEN); - if (hw->chip_id == CHIP_ID_GENESIS) - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - else { - gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); - gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + /* disable Rx */ + ctrl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); + + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); + + if (netif_running(dev)) { + if (hw->chip_id == CHIP_ID_GENESIS) + xm_outaddr(hw, port, XM_SA, dev->dev_addr); + else { + gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); + gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + } } - mutex_unlock(&hw->phy_mutex); + + gma_write16(hw, port, GM_GP_CTRL, ctrl); return 0; } -- cgit v1.2.2 From 8b902aea40544bc9e4de913b491dc3a3411fd5d0 Mon Sep 17 00:00:00 2001 From: Linsys Contractor Mithlesh Thukral Date: Tue, 13 Mar 2007 04:13:13 -0800 Subject: NetXen: Bug fix for Jumbo frames on XG card NetXen: Set the MTU for the right port depending upon the port number for XG cards. Signed-off by: Mithlesh Thukral Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_hw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 1be55702557d..6537574a9cda 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -822,7 +822,10 @@ int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu) { struct netxen_adapter *adapter = port->adapter; new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE; - netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + if (port->portnum == 0) + netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + else if (port->portnum == 1) + netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu); return 0; } -- cgit v1.2.2 From b58ecad8d6ca83e97cd2928a439efb49267539dc Mon Sep 17 00:00:00 2001 From: Linsys Contractor Mithlesh Thukral Date: Tue, 13 Mar 2007 04:15:06 -0800 Subject: NetXen: Fix softlockup seen during hardware access NetXen: This will fix a softlock seen on some machines. The reason was too much time was spent waiting for hardware access to go through. Signed-off by: Mithlesh Thukral Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 1 + drivers/net/netxen/netxen_nic_ethtool.c | 1 + drivers/net/netxen/netxen_nic_init.c | 11 +++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 81742e4e5610..dd8ce35332fe 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -232,6 +232,7 @@ enum { #define MPORT_SINGLE_FUNCTION_MODE 0x1111 extern unsigned long long netxen_dma_mask; +extern unsigned long last_schedule_time; /* * NetXen host-peg signal message structure diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 986ef98db229..ee1b5a24cbe7 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -462,6 +462,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, } printk(KERN_INFO "%s: flash unlocked. \n", netxen_nic_driver_name); + last_schedule_time = jiffies; ret = netxen_flash_erase_secondary(adapter); if (ret != FLASH_SUCCESS) { printk(KERN_ERR "%s: Flash erase failed.\n", diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 586d32b676af..229aa1c4fb79 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -42,6 +42,8 @@ struct crb_addr_pair { u32 data; }; +unsigned long last_schedule_time; + #define NETXEN_MAX_CRB_XFORM 60 static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; #define NETXEN_ADDR_ERROR (0xffffffff) @@ -404,9 +406,14 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static inline int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { + if (jiffies > (last_schedule_time + (8 * HZ))) { + last_schedule_time = jiffies; + schedule(); + } + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - udelay(70); /* prevent bursting on CRB */ + 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_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { @@ -415,7 +422,7 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) } /* reset abyte_cnt and dummy_byte_cnt */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - udelay(70); /* prevent bursting on CRB */ + udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); -- cgit v1.2.2 From 14fdd90ef2ec1878d6851ec4dd8d5abb2cef098c Mon Sep 17 00:00:00 2001 From: "broonie@sirena.org.uk" Date: Wed, 14 Mar 2007 19:49:13 +0000 Subject: natsemi: Consistently use interrupt enable/disable functions The natsemi drivers include functions for enabling and disabling interrupts from the chip but these are not used in all code paths. This patch changes the code paths that touch the interrupt enable register to use the functions. In all cases this adds an extra PCI read to post the operation but since none of these are in fast paths this shouldn't be too much of a problem. Signed-Off-By: Mark Brown Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c6172a77a6d7..2888880df3b7 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -1712,7 +1712,7 @@ static void init_registers(struct net_device *dev) /* Enable interrupts by setting the interrupt mask. */ writel(DEFAULT_INTR, ioaddr + IntrMask); - writel(1, ioaddr + IntrEnable); + natsemi_irq_enable(dev); writel(RxOn | TxOn, ioaddr + ChipCmd); writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */ @@ -3071,7 +3071,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr) * Could be used to send a netlink message. */ writel(WOLPkt | LinkChange, ioaddr + IntrMask); - writel(1, ioaddr + IntrEnable); + natsemi_irq_enable(dev); } } @@ -3202,7 +3202,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state) disable_irq(dev->irq); spin_lock_irq(&np->lock); - writel(0, ioaddr + IntrEnable); + natsemi_irq_disable(dev); np->hands_off = 1; natsemi_stop_rxtx(dev); netif_stop_queue(dev); -- cgit v1.2.2 From 069f8256362b7a17da532f0631cee73b4cfee65b Mon Sep 17 00:00:00 2001 From: "broonie@sirena.org.uk" Date: Wed, 14 Mar 2007 19:49:14 +0000 Subject: natsemi: Fix NAPI for interrupt sharing The interrupt status register for the natsemi chips is clear on read and was read unconditionally from both the interrupt and from the NAPI poll routine, meaning that if the interrupt service routine was called (for example, due to a shared interrupt) while a NAPI poll was scheduled interrupts could be missed. This patch fixes that by ensuring that the interrupt status register is only read by the interrupt handler when interrupts are enabled from the chip. It also reverts a workaround for this problem from the netpoll hook and improves the trace for interrupt events. Thanks to Sergei Shtylyov for spotting the issue, Mark Huth for a simpler method and Simon Blake for testing resources. Signed-Off-By: Mark Brown Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 2888880df3b7..5f88200724e6 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2119,28 +2119,35 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) struct netdev_private *np = netdev_priv(dev); void __iomem * ioaddr = ns_ioaddr(dev); - if (np->hands_off) + /* Reading IntrStatus automatically acknowledges so don't do + * that while interrupts are disabled, (for example, while a + * poll is scheduled). */ + if (np->hands_off || !readl(ioaddr + IntrEnable)) return IRQ_NONE; - /* Reading automatically acknowledges. */ np->intr_status = readl(ioaddr + IntrStatus); + if (!np->intr_status) + return IRQ_NONE; + if (netif_msg_intr(np)) printk(KERN_DEBUG "%s: Interrupt, status %#08x, mask %#08x.\n", dev->name, np->intr_status, readl(ioaddr + IntrMask)); - if (!np->intr_status) - return IRQ_NONE; - prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]); if (netif_rx_schedule_prep(dev)) { /* Disable interrupts and register for poll */ natsemi_irq_disable(dev); __netif_rx_schedule(dev); - } + } else + printk(KERN_WARNING + "%s: Ignoring interrupt, status %#08x, mask %#08x.\n", + dev->name, np->intr_status, + readl(ioaddr + IntrMask)); + return IRQ_HANDLED; } @@ -2156,6 +2163,12 @@ static int natsemi_poll(struct net_device *dev, int *budget) int work_done = 0; do { + if (netif_msg_intr(np)) + printk(KERN_DEBUG + "%s: Poll, status %#08x, mask %#08x.\n", + dev->name, np->intr_status, + readl(ioaddr + IntrMask)); + if (np->intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { spin_lock(&np->lock); @@ -2399,19 +2412,8 @@ static struct net_device_stats *get_stats(struct net_device *dev) #ifdef CONFIG_NET_POLL_CONTROLLER static void natsemi_poll_controller(struct net_device *dev) { - struct netdev_private *np = netdev_priv(dev); - disable_irq(dev->irq); - - /* - * A real interrupt might have already reached us at this point - * but NAPI might still haven't called us back. As the interrupt - * status register is cleared by reading, we should prevent an - * interrupt loss in this case... - */ - if (!np->intr_status) - intr_handler(dev->irq, dev); - + intr_handler(dev->irq, dev); enable_irq(dev->irq); } #endif -- cgit v1.2.2 From d2a900365b8963d7ca46f05d8e7176d1be3cc71d Mon Sep 17 00:00:00 2001 From: "broonie@sirena.org.uk" Date: Wed, 14 Mar 2007 19:49:15 +0000 Subject: natsemi: Avoid IntrStatus lossage if RX state machine resets. This patch fixes the poll routine for the natsemi driver so that if the driver detects an RX state machine lockup then no interrupts will be lost while the driver recovers from that. Signed-Off-By: Mark Brown Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 5f88200724e6..349b96a3ec4c 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2169,6 +2169,14 @@ static int natsemi_poll(struct net_device *dev, int *budget) dev->name, np->intr_status, readl(ioaddr + IntrMask)); + /* netdev_rx() may read IntrStatus again if the RX state + * machine falls over so do it first. */ + if (np->intr_status & + (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | + IntrRxErr | IntrRxOverrun)) { + netdev_rx(dev, &work_done, work_to_do); + } + if (np->intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr)) { spin_lock(&np->lock); @@ -2180,12 +2188,6 @@ static int natsemi_poll(struct net_device *dev, int *budget) if (np->intr_status & IntrAbnormalSummary) netdev_error(dev, np->intr_status); - if (np->intr_status & - (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | - IntrRxErr | IntrRxOverrun)) { - netdev_rx(dev, &work_done, work_to_do); - } - *budget -= work_done; dev->quota -= work_done; -- cgit v1.2.2 From 21665a69e6c0c3e383eaef417f0ddbd16bdb69e3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 14 Mar 2007 10:32:07 -0500 Subject: [PATCH] bcm43xx: MANUALWLAN fixes During testing of bcm43xx interference mitigation, two problems were discovered: (1) When the MANUALWLAN mode was set, routines _stack_save and _stack_restore generated assertions that were traced to saving ILT registers with addresses > 0xFFF. This problem was fixed by adding one bit to the field used for the offset, and subtracting one bit from the space used for the id. (2) In MANUALWLAN mode, the IRQ XMIT errors are generated. The cause of these errors has not yet been located. Any suggestions on debugging this problem would be greatly appreciated. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 32beb91b7164..ee1e7a2afc08 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -882,10 +882,10 @@ static void _stack_save(u32 *_stackptr, size_t *stackidx, { u32 *stackptr = &(_stackptr[*stackidx]); - assert((offset & 0xF000) == 0x0000); - assert((id & 0xF0) == 0x00); + assert((offset & 0xE000) == 0x0000); + assert((id & 0xF8) == 0x00); *stackptr = offset; - *stackptr |= ((u32)id) << 12; + *stackptr |= ((u32)id) << 13; *stackptr |= ((u32)value) << 16; (*stackidx)++; assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); @@ -896,12 +896,12 @@ static u16 _stack_restore(u32 *stackptr, { size_t i; - assert((offset & 0xF000) == 0x0000); - assert((id & 0xF0) == 0x00); + assert((offset & 0xE000) == 0x0000); + assert((id & 0xF8) == 0x00); for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00000FFF) != offset) + if ((*stackptr & 0x00001FFF) != offset) continue; - if (((*stackptr & 0x0000F000) >> 12) != id) + if (((*stackptr & 0x00007000) >> 13) != id) continue; return ((*stackptr & 0xFFFF0000) >> 16); } -- cgit v1.2.2 From 4d881901b8c2167884d213eb546ffffc9e5e35ac Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Fri, 16 Mar 2007 12:42:59 +0100 Subject: [PATCH] airo: Fix an error path memory leak The airo driver leaks memory if request_irq() fails. Signed-off-by: Michal Schmidt Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a8c2bfe26c27..2ada76a93cb6 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2852,7 +2852,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (rc) { airo_print_err(dev->name, "register interrupt %d failed, rc %d", irq, rc); - goto err_out_unlink; + goto err_out_nets; } if (!is_pcmcia) { if (!request_region( dev->base_addr, 64, dev->name )) { @@ -2935,6 +2935,8 @@ err_out_res: release_region( dev->base_addr, 64 ); err_out_irq: free_irq(dev->irq, dev); +err_out_nets: + airo_networks_free(ai); err_out_unlink: del_airo_dev(dev); err_out_thr: -- cgit v1.2.2 From 2e360d81ea1fe1a7701e05cdefd3a91c11c3b13f Mon Sep 17 00:00:00 2001 From: Nigel Williams Date: Fri, 16 Mar 2007 20:28:36 -0700 Subject: [IrDA]: Delay needed when uploading firmware chunks With 42101001.sb firmwares, we need a 10 ms delay between firmware chunks upload on irda-usb. Patch from Nigel Williams Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller --- drivers/net/irda/irda-usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 340ee99652eb..1d510bdc9b84 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1057,6 +1057,8 @@ static int stir421x_fw_upload(struct irda_usb_cb *self, if (ret < 0) break; + + mdelay(10); } kfree(patch_block); -- cgit v1.2.2 From e3a1b99fb60dab1b39d5022d1d8f47bebfe6d8c6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 16 Mar 2007 14:01:26 -0700 Subject: skge: deadlock on tx timeout The skge driver will deadlock if gets a transmit timeout because the netif_tx_lock() is already held. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 8fecf1b817f7..fad189e01ec6 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2576,7 +2576,11 @@ static int skge_down(struct net_device *dev) skge_led(skge, LED_MODE_OFF); netif_poll_disable(dev); + + netif_tx_lock_bh(dev); skge_tx_clean(dev); + netif_tx_unlock_bh(dev); + skge_rx_clean(skge); kfree(skge->rx_ring.start); @@ -2721,7 +2725,6 @@ static void skge_tx_clean(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_element *e; - netif_tx_lock_bh(dev); for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { struct skge_tx_desc *td = e->desc; skge_tx_free(skge, e, td->control); @@ -2730,7 +2733,6 @@ static void skge_tx_clean(struct net_device *dev) skge->tx_ring.to_clean = e; netif_wake_queue(dev); - netif_tx_unlock_bh(dev); } static void skge_tx_timeout(struct net_device *dev) -- cgit v1.2.2 From 4ebabfcb1d6af5191ef5c8305717ccbc24979f6c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 16 Mar 2007 14:01:27 -0700 Subject: skge: mask irqs when device down Wheen a port on the skge driver is not used, it should mask off interrupts from theat port. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index fad189e01ec6..6e1eb23d93c4 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -105,7 +105,8 @@ static const int txqaddr[] = { Q_XA1, Q_XA2 }; static const int rxqaddr[] = { Q_R1, Q_R2 }; static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; +static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; +static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; static int skge_get_regs_len(struct net_device *dev) { @@ -2504,6 +2505,11 @@ static int skge_up(struct net_device *dev) skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); skge_led(skge, LED_MODE_ON); + spin_lock_irq(&hw->hw_lock); + hw->intr_mask |= portmask[port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock_irq(&hw->hw_lock); + netif_poll_enable(dev); return 0; @@ -2533,6 +2539,13 @@ static int skge_down(struct net_device *dev) if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) cancel_delayed_work(&skge->link_thread); + netif_poll_disable(dev); + + spin_lock_irq(&hw->hw_lock); + hw->intr_mask &= ~portmask[port]; + skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock_irq(&hw->hw_lock); + skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); if (hw->chip_id == CHIP_ID_GENESIS) genesis_stop(skge); @@ -2575,8 +2588,6 @@ static int skge_down(struct net_device *dev) skge_led(skge, LED_MODE_OFF); - netif_poll_disable(dev); - netif_tx_lock_bh(dev); skge_tx_clean(dev); netif_tx_unlock_bh(dev); @@ -3051,7 +3062,7 @@ static int skge_poll(struct net_device *dev, int *budget) spin_lock_irqsave(&hw->hw_lock, flags); __netif_rx_complete(dev); - hw->intr_mask |= irqmask[skge->port]; + hw->intr_mask |= napimask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); skge_read32(hw, B0_IMSK); spin_unlock_irqrestore(&hw->hw_lock, flags); @@ -3415,10 +3426,9 @@ static int skge_reset(struct skge_hw *hw) else hw->ram_size = t8 * 4096; - hw->intr_mask = IS_HW_ERR | IS_PORT_1; - if (hw->ports > 1) - hw->intr_mask |= IS_PORT_2; + hw->intr_mask = IS_HW_ERR; + /* Use PHY IRQ for all but fiber based Genesis board */ if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)) hw->intr_mask |= IS_EXT_REG; -- cgit v1.2.2 From 9cbe330f1fbbc8de15a5914aa6e91d89eb9daac4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 16 Mar 2007 14:01:28 -0700 Subject: skge: use per-port phy locking Rather than a workqueue and a per-board mutex to control PHY, use a tasklet and spinlock. Tasklet is lower overhead and works just as well for this. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 82 +++++++++++++++++++++++++++++------------------------- drivers/net/skge.h | 6 ++-- 2 files changed, 47 insertions(+), 41 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 6e1eb23d93c4..39c6677dff5e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -672,7 +672,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) struct skge_hw *hw = skge->hw; int port = skge->port; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { switch (mode) { case LED_MODE_OFF: @@ -743,7 +743,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) PHY_M_LED_MO_RX(MO_LED_ON)); } } - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); } /* blink LED's for finding board */ @@ -1317,7 +1317,7 @@ static void xm_phy_init(struct skge_port *skge) xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl); /* Poll PHY for status changes */ - schedule_delayed_work(&skge->link_thread, LINK_HZ); + mod_timer(&skge->link_timer, jiffies + LINK_HZ); } static void xm_check_link(struct net_device *dev) @@ -1392,10 +1392,9 @@ static void xm_check_link(struct net_device *dev) * Since internal PHY is wired to a level triggered pin, can't * get an interrupt when carrier is detected. */ -static void xm_link_timer(struct work_struct *work) +static void xm_link_timer(unsigned long arg) { - struct skge_port *skge = - container_of(work, struct skge_port, link_thread.work); + struct skge_port *skge = (struct skge_port *) arg; struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; @@ -1415,13 +1414,13 @@ static void xm_link_timer(struct work_struct *work) goto nochange; } - mutex_lock(&hw->phy_mutex); + spin_lock(&hw->phy_lock); xm_check_link(dev); - mutex_unlock(&hw->phy_mutex); + spin_unlock(&hw->phy_lock); nochange: if (netif_running(dev)) - schedule_delayed_work(&skge->link_thread, LINK_HZ); + mod_timer(&skge->link_timer, jiffies + LINK_HZ); } static void genesis_mac_init(struct skge_hw *hw, int port) @@ -2324,7 +2323,7 @@ static void skge_phy_reset(struct skge_port *skge) netif_stop_queue(skge->netdev); netif_carrier_off(skge->netdev); - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { genesis_reset(hw, port); genesis_mac_init(hw, port); @@ -2332,7 +2331,7 @@ static void skge_phy_reset(struct skge_port *skge) yukon_reset(hw, port); yukon_init(hw, port); } - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); dev->set_multicast_list(dev); } @@ -2355,12 +2354,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* fallthru */ case SIOCGMIIREG: { u16 val = 0; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); else err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); data->val_out = val; break; } @@ -2369,14 +2368,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); else err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); break; } return err; @@ -2482,12 +2481,12 @@ static int skge_up(struct net_device *dev) goto free_rx_ring; /* Initialize MAC */ - mutex_lock(&hw->phy_mutex); + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); - mutex_unlock(&hw->phy_mutex); + spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); @@ -2537,7 +2536,7 @@ static int skge_down(struct net_device *dev) netif_stop_queue(dev); if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) - cancel_delayed_work(&skge->link_thread); + del_timer_sync(&skge->link_timer); netif_poll_disable(dev); @@ -3173,28 +3172,29 @@ static void skge_error_irq(struct skge_hw *hw) } /* - * Interrupt from PHY are handled in work queue + * Interrupt from PHY are handled in tasklet (softirq) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(struct work_struct *work) +static void skge_extirq(unsigned long arg) { - struct skge_hw *hw = container_of(work, struct skge_hw, phy_work); + struct skge_hw *hw = (struct skge_hw *) arg; int port; - mutex_lock(&hw->phy_mutex); for (port = 0; port < hw->ports; port++) { struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); if (netif_running(dev)) { + struct skge_port *skge = netdev_priv(dev); + + spin_lock(&hw->phy_lock); if (hw->chip_id != CHIP_ID_GENESIS) yukon_phy_intr(skge); else if (hw->phy_type == SK_PHY_BCOM) bcom_phy_intr(skge); + spin_unlock(&hw->phy_lock); } } - mutex_unlock(&hw->phy_mutex); spin_lock_irq(&hw->hw_lock); hw->intr_mask |= IS_EXT_REG; @@ -3219,7 +3219,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id) status &= hw->intr_mask; if (status & IS_EXT_REG) { hw->intr_mask &= ~IS_EXT_REG; - schedule_work(&hw->phy_work); + tasklet_schedule(&hw->phy_task); } if (status & (IS_XA1_F|IS_R1_F)) { @@ -3295,23 +3295,28 @@ static int skge_set_mac_address(struct net_device *dev, void *p) memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - /* disable Rx */ - ctrl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); + if (!netif_running(dev)) { + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); + } else { + /* disable Rx */ + spin_lock_bh(&hw->phy_lock); + ctrl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); - memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - if (netif_running(dev)) { if (hw->chip_id == CHIP_ID_GENESIS) xm_outaddr(hw, port, XM_SA, dev->dev_addr); else { gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); } - } - gma_write16(hw, port, GM_GP_CTRL, ctrl); + gma_write16(hw, port, GM_GP_CTRL, ctrl); + spin_unlock_bh(&hw->phy_lock); + } return 0; } @@ -3496,14 +3501,12 @@ static int skge_reset(struct skge_hw *hw) skge_write32(hw, B0_IMSK, hw->intr_mask); - mutex_lock(&hw->phy_mutex); for (i = 0; i < hw->ports; i++) { if (hw->chip_id == CHIP_ID_GENESIS) genesis_reset(hw, i); else yukon_reset(hw, i); } - mutex_unlock(&hw->phy_mutex); return 0; } @@ -3551,6 +3554,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->netdev = dev; skge->hw = hw; skge->msg_enable = netif_msg_init(debug, default_msg); + skge->tx_ring.count = DEFAULT_TX_RING_SIZE; skge->rx_ring.count = DEFAULT_RX_RING_SIZE; @@ -3567,7 +3571,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer); + setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; @@ -3649,9 +3653,9 @@ static int __devinit skge_probe(struct pci_dev *pdev, } hw->pdev = pdev; - mutex_init(&hw->phy_mutex); - INIT_WORK(&hw->phy_work, skge_extirq); spin_lock_init(&hw->hw_lock); + spin_lock_init(&hw->phy_lock); + tasklet_init(&hw->phy_task, &skge_extirq, (unsigned long) hw); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { @@ -3737,6 +3741,8 @@ static void __devexit skge_remove(struct pci_dev *pdev) dev0 = hw->dev[0]; unregister_netdev(dev0); + tasklet_disable(&hw->phy_task); + spin_lock_irq(&hw->hw_lock); hw->intr_mask = 0; skge_write32(hw, B0_IMSK, 0); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index e9354dfa7e9a..86467ae74d45 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2424,8 +2424,8 @@ struct skge_hw { u32 ram_size; u32 ram_offset; u16 phy_addr; - struct work_struct phy_work; - struct mutex phy_mutex; + spinlock_t phy_lock; + struct tasklet_struct phy_task; }; enum pause_control { @@ -2457,7 +2457,7 @@ struct skge_port { struct net_device_stats net_stats; - struct delayed_work link_thread; + struct timer_list link_timer; enum pause_control flow_control; enum pause_status flow_status; u8 rx_csum; -- cgit v1.2.2 From 5c4851ccb6b12ff29e28b84e7515a18006b19fdf Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 16 Mar 2007 17:00:21 -0500 Subject: Fix return code in pci-skeleton.c We assign the return value of register_netdev to i, but return rc later on. Fix it. Signed-off-by: Anton Blanchard Signed-off-by: Jeff Garzik --- drivers/net/pci-skeleton.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 00ca0fdb837b..6ca4e4fa6b88 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -710,8 +710,8 @@ match: tp->chipset, rtl_chip_info[tp->chipset].name); - i = register_netdev (dev); - if (i) + rc = register_netdev (dev); + if (rc) goto err_out_unmap; DPRINTK ("EXIT, returning 0\n"); -- cgit v1.2.2 From 05b97b30b09ed245d376035cddf669532e5cca67 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Mar 2007 13:10:01 -0700 Subject: cxgb3 - fix ethtool cmd on multiple queues port Limit ethtool -g/-G to the given port's queues. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7ff834e45d6b..eb0a4e068200 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1362,23 +1362,27 @@ static int set_rx_csum(struct net_device *dev, u32 data) static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { - struct adapter *adapter = dev->priv; + const struct adapter *adapter = dev->priv; + const struct port_info *pi = netdev_priv(dev); + const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset]; e->rx_max_pending = MAX_RX_BUFFERS; e->rx_mini_max_pending = 0; e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS; e->tx_max_pending = MAX_TXQ_ENTRIES; - e->rx_pending = adapter->params.sge.qset[0].fl_size; - e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size; - e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size; - e->tx_pending = adapter->params.sge.qset[0].txq_size[0]; + e->rx_pending = q->fl_size; + e->rx_mini_pending = q->rspq_size; + e->rx_jumbo_pending = q->jumbo_size; + e->tx_pending = q->txq_size[0]; } static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) { int i; + struct qset_params *q; struct adapter *adapter = dev->priv; + const struct port_info *pi = netdev_priv(dev); if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || @@ -1393,9 +1397,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) if (adapter->flags & FULL_INIT_DONE) return -EBUSY; - for (i = 0; i < SGE_QSETS; ++i) { - struct qset_params *q = &adapter->params.sge.qset[i]; - + q = &adapter->params.sge.qset[pi->first_qset]; + for (i = 0; i < pi->nqsets; ++i, ++q) { q->rspq_size = e->rx_mini_pending; q->fl_size = e->rx_pending; q->jumbo_size = e->rx_jumbo_pending; -- cgit v1.2.2 From 2e2839627a957714808f98a802d137a7a2a1df46 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Mar 2007 13:10:06 -0700 Subject: cxgb3 - Auto-load FW if mismatch detected The driver attempts to upgrade the FW if the card has the wrong version. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + drivers/net/cxgb3/cxgb3_main.c | 25 +++++++++++++++++++++++++ drivers/net/cxgb3/t3_hw.c | 5 +++-- 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5ff0922e628c..1b6459b218ca 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2374,6 +2374,7 @@ config CHELSIO_T1_NAPI config CHELSIO_T3 tristate "Chelsio Communications T3 10Gb Ethernet support" depends on PCI + select FW_LOADER help This driver supports Chelsio T3-based gigabit and 10Gb Ethernet adapters. diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index eb0a4e068200..b9bcda821f7c 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "common.h" @@ -707,6 +708,28 @@ static void bind_qsets(struct adapter *adap) } } +#define FW_FNAME "t3fw-%d.%d.bin" + +static int upgrade_fw(struct adapter *adap) +{ + int ret; + char buf[64]; + const struct firmware *fw; + struct device *dev = &adap->pdev->dev; + + snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, + FW_VERSION_MINOR); + ret = request_firmware(&fw, buf, dev); + if (ret < 0) { + dev_err(dev, "could not upgrade firmware: unable to load %s\n", + buf); + return ret; + } + ret = t3_load_fw(adap, fw->data, fw->size); + release_firmware(fw); + return ret; +} + /** * cxgb_up - enable the adapter * @adapter: adapter being enabled @@ -723,6 +746,8 @@ static int cxgb_up(struct adapter *adap) if (!(adap->flags & FULL_INIT_DONE)) { err = t3_check_fw_version(adap); + if (err == -EINVAL) + err = upgrade_fw(adap); if (err) goto out; diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index eaa7a2e89a30..983ee813c7e4 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -681,7 +681,8 @@ enum { SF_ERASE_SECTOR = 0xd8, /* erase sector */ FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ - FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */ + FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */ + FW_MIN_SIZE = 8 /* at least version and csum */ }; /** @@ -935,7 +936,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size) const u32 *p = (const u32 *)fw_data; int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16; - if (size & 3) + if ((size & 3) || size < FW_MIN_SIZE) return -EINVAL; if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR) return -EFBIG; -- cgit v1.2.2 From fc90664e3438c990d280f179ccb0642711d5c553 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Mar 2007 13:10:12 -0700 Subject: cxgb3 - Fix potential MAC hang Under rare conditions, the MAC might hang while generating a pause frame. This patch fine tunes the MAC settings to avoid the issue, allows for periodic MAC state check, and triggers a recovery if hung. Also fix one MAC statistics counter for the rev board T3B2. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/common.h | 15 +++++ drivers/net/cxgb3/cxgb3_main.c | 46 +++++++++++++- drivers/net/cxgb3/regs.h | 22 +++++++ drivers/net/cxgb3/xgmac.c | 133 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 200 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index e23deeb7d06d..85e5543cfb57 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -260,6 +260,10 @@ struct mac_stats { unsigned long serdes_signal_loss; unsigned long xaui_pcs_ctc_err; unsigned long xaui_pcs_align_change; + + unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */ + unsigned long num_resets; /* # times reset due to stuck TX */ + }; struct tp_mib_stats { @@ -400,6 +404,12 @@ struct adapter_params { unsigned int rev; /* chip revision */ }; +enum { /* chip revisions */ + T3_REV_A = 0, + T3_REV_B = 2, + T3_REV_B2 = 3, +}; + struct trace_params { u32 sip; u32 sip_mask; @@ -465,6 +475,10 @@ struct cmac { struct adapter *adapter; unsigned int offset; unsigned int nucast; /* # of address filters for unicast MACs */ + unsigned int tcnt; + unsigned int xcnt; + unsigned int toggle_cnt; + unsigned int txen; struct mac_stats stats; }; @@ -666,6 +680,7 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]); int t3_mac_set_num_ucast(struct cmac *mac, int n); const struct mac_stats *t3_mac_update_stats(struct cmac *mac); int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc); +int t3b2_mac_watchdog_task(struct cmac *mac); void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode); int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index b9bcda821f7c..d55383610559 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1056,7 +1056,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "VLANinsertions ", "TxCsumOffload ", "RxCsumGood ", - "RxDrops " + "RxDrops ", + + "CheckTXEnToggled ", + "CheckResets ", + }; static int get_stats_count(struct net_device *dev) @@ -1170,6 +1174,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); *data++ = s->rx_cong_drops; + + *data++ = s->num_toggled; + *data++ = s->num_resets; } static inline void reg_block_dump(struct adapter *ap, void *buf, @@ -2095,6 +2102,40 @@ static void check_link_status(struct adapter *adapter) } } +static void check_t3b2_mac(struct adapter *adapter) +{ + int i; + + rtnl_lock(); /* synchronize with ifdown */ + for_each_port(adapter, i) { + struct net_device *dev = adapter->port[i]; + struct port_info *p = netdev_priv(dev); + int status; + + if (!netif_running(dev)) + continue; + + status = 0; + if (netif_running(dev)) + status = t3b2_mac_watchdog_task(&p->mac); + if (status == 1) + p->mac.stats.num_toggled++; + else if (status == 2) { + struct cmac *mac = &p->mac; + + t3_mac_set_mtu(mac, dev->mtu); + t3_mac_set_address(mac, 0, dev->dev_addr); + cxgb_set_rxmode(dev); + t3_link_start(&p->phy, mac, &p->link_config); + t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); + t3_port_intr_enable(adapter, p->port_id); + p->mac.stats.num_resets++; + } + } + rtnl_unlock(); +} + + static void t3_adap_check_task(struct work_struct *work) { struct adapter *adapter = container_of(work, struct adapter, @@ -2115,6 +2156,9 @@ static void t3_adap_check_task(struct work_struct *work) adapter->check_task_cnt = 0; } + if (p->rev == T3_REV_B2) + check_t3b2_mac(adapter); + /* Schedule the next check update if any port is active. */ spin_lock(&adapter->work_lock); if (adapter->open_device_map & PORT_MASK) diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index b56c5f52bcdc..b38629a244d0 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1206,6 +1206,14 @@ #define A_TP_RX_TRC_KEY0 0x120 +#define A_TP_TX_DROP_CNT_CH0 0x12d + +#define S_TXDROPCNTCH0RCVD 0 +#define M_TXDROPCNTCH0RCVD 0xffff +#define V_TXDROPCNTCH0RCVD(x) ((x) << S_TXDROPCNTCH0RCVD) +#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \ + M_TXDROPCNTCH0RCVD) + #define A_ULPRX_CTL 0x500 #define S_ROUND_ROBIN 4 @@ -1834,6 +1842,8 @@ #define V_TXPAUSEEN(x) ((x) << S_TXPAUSEEN) #define F_TXPAUSEEN V_TXPAUSEEN(1U) +#define A_XGM_TX_PAUSE_QUANTA 0x808 + #define A_XGM_RX_CTRL 0x80c #define S_RXEN 0 @@ -1920,6 +1930,11 @@ #define A_XGM_TXFIFO_CFG 0x888 +#define S_TXIPG 13 +#define M_TXIPG 0xff +#define V_TXIPG(x) ((x) << S_TXIPG) +#define G_TXIPG(x) (((x) >> S_TXIPG) & M_TXIPG) + #define S_TXFIFOTHRESH 4 #define M_TXFIFOTHRESH 0x1ff @@ -2190,6 +2205,13 @@ #define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4 +#define A_XGM_TX_SPI4_SOP_EOP_CNT 0x9a8 + +#define S_TXSPI4SOPCNT 16 +#define M_TXSPI4SOPCNT 0xffff +#define V_TXSPI4SOPCNT(x) ((x) << S_TXSPI4SOPCNT) +#define G_TXSPI4SOPCNT(x) (((x) >> S_TXSPI4SOPCNT) & M_TXSPI4SOPCNT) + #define A_XGM_RX_SPI4_SOP_EOP_CNT 0x9ac #define XGMAC0_1_BASE_ADDR 0xa00 diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 907a272ae32d..2b42c13ba8e0 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -124,9 +124,6 @@ int t3_mac_reset(struct cmac *mac) xaui_serdes_reset(mac); } - if (adap->params.rev > 0) - t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000); - val = F_MAC_RESET_; if (is_10G(adap)) val |= F_PCS_RESET_; @@ -145,6 +142,58 @@ int t3_mac_reset(struct cmac *mac) return 0; } +int t3b2_mac_reset(struct cmac *mac) +{ + struct adapter *adap = mac->adapter; + unsigned int oft = mac->offset; + u32 val; + + if (!macidx(mac)) + t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); + else + t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); + + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + + msleep(10); + + /* Check for xgm Rx fifo empty */ + if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, + 0x80000000, 1, 5, 2)) { + CH_ERR(adap, "MAC %d Rx fifo drain failed\n", + macidx(mac)); + return -1; + } + + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + + val = F_MAC_RESET_; + if (is_10G(adap)) + val |= F_PCS_RESET_; + else if (uses_xaui(adap)) + val |= F_PCS_RESET_ | F_XG2G_RESET_; + else + val |= F_RGMII_RESET_ | F_XG2G_RESET_; + t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); + t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ + if ((val & F_PCS_RESET_) && adap->params.rev) { + msleep(1); + t3b_pcs_reset(mac); + } + t3_write_reg(adap, A_XGM_RX_CFG + oft, + F_DISPAUSEFRAMES | F_EN1536BFRAMES | + F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); + + if (!macidx(mac)) + t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); + else + t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); + + return 0; +} + /* * Set the exact match register 'idx' to recognize the given Ethernet address. */ @@ -251,9 +300,11 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) * Adjust the PAUSE frame watermarks. We always set the LWM, and the * HWM only if flow-control is enabled. */ - hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U); - hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024); - lwm = hwm - 1024; + hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu, + MAC_RXFIFO_SIZE * 38 / 100); + hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); + lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); + v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); v |= V_RXFIFOPAUSELWM(lwm / 8); @@ -270,7 +321,15 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; thres = max(thres, 8U); /* need at least 8 */ t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, - V_TXFIFOTHRESH(M_TXFIFOTHRESH), V_TXFIFOTHRESH(thres)); + V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), + V_TXFIFOTHRESH(thres) | V_TXIPG(1)); + + if (adap->params.rev > 0) + t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, + (hwm - lwm) * 4 / 8); + t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, + MAC_RXFIFO_SIZE * 4 * 8 / 512); + return 0; } @@ -298,12 +357,6 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) V_PORTSPEED(M_PORTSPEED), val); } - val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); - val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); - if (fc & PAUSE_TX) - val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */ - t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); - t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); return 0; @@ -318,9 +371,17 @@ int t3_mac_enable(struct cmac *mac, int which) if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xbf000001); + t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); + mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, + A_TP_PIO_DATA))); + mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT))); + mac->txen = F_TXEN; + mac->toggle_cnt = 0; } if (which & MAC_DIRECTION_RX) t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); @@ -337,13 +398,50 @@ int t3_mac_disable(struct cmac *mac, int which) t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 0); + t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + mac->txen = 0; } if (which & MAC_DIRECTION_RX) t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); return 0; } +int t3b2_mac_watchdog_task(struct cmac *mac) +{ + struct adapter *adap = mac->adapter; + unsigned int tcnt, xcnt; + int status; + + t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac)); + tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); + xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT + + mac->offset))); + + if (tcnt != mac->tcnt && xcnt == 0 && mac->xcnt == 0) { + if (mac->toggle_cnt > 4) { + t3b2_mac_reset(mac); + mac->toggle_cnt = 0; + status = 2; + } else { + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, + mac->txen); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); + mac->toggle_cnt++; + status = 1; + } + } else { + mac->toggle_cnt = 0; + status = 0; + } + mac->tcnt = tcnt; + mac->xcnt = xcnt; + + return status; +} + /* * This function is called periodically to accumulate the current values of the * RMON counters into the port statistics. Since the packet counters are only @@ -375,6 +473,11 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac) RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); + v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); + if (mac->adapter->params.rev == T3_REV_B2) + v &= 0x7fffffff; + mac->stats.rx_too_long += v; + RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); -- cgit v1.2.2 From e4d08359ffb6580ee7a014d162162b2d18aa4ec0 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 18 Mar 2007 13:10:17 -0700 Subject: cxgb3 - T3B2 pcie config space T3B2 does not lose its pcie config space on reset. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/t3_hw.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 983ee813c7e4..791ed6dc1943 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -3244,15 +3244,17 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) } /* - * Reset the adapter. PCIe cards lose their config space during reset, PCI-X + * Reset the adapter. + * Older PCIe cards lose their config space during reset, PCI-X * ones don't. */ int t3_reset_adapter(struct adapter *adapter) { - int i; + int i, save_and_restore_pcie = + adapter->params.rev < T3_REV_B2 && is_pcie(adapter); uint16_t devid = 0; - if (is_pcie(adapter)) + if (save_and_restore_pcie) pci_save_state(adapter->pdev); t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE); @@ -3270,7 +3272,7 @@ int t3_reset_adapter(struct adapter *adapter) if (devid != 0x1425) return -1; - if (is_pcie(adapter)) + if (save_and_restore_pcie) pci_restore_state(adapter->pdev); return 0; } -- cgit v1.2.2 From 6f6881b846e3d97ee15f6ab1f6529cd1cc2f4c28 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Mon, 19 Mar 2007 11:58:02 +0800 Subject: Revert "ucc_geth: returns NETDEV_TX_BUSY when BD ring is full" This reverts commit 18babd38547a042a4bfd4154a014d1ad33373eb0. Michael Barkowski points out that it's wrong, and I agree. The patch causes a problem rather than fixes one after another patch "ucc_geth: Fix BD processing" was applied. Before that patch, current packet should be blocked. However after the patch current packet is ok and we only need to block next. Reported-by: Michael Barkowski Signed-off-by: Li Yang Signed-off-by: Jeff Garzik --- drivers/net/ucc_geth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index dab88b958d6e..639e1e6913bf 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3607,7 +3607,6 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bd == ugeth->confBd[txQ]) { if (!netif_queue_stopped(dev)) netif_stop_queue(dev); - return NETDEV_TX_BUSY; } ugeth->txBd[txQ] = bd; @@ -3623,7 +3622,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irq(&ugeth->lock); - return NETDEV_TX_OK; + return 0; } static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) -- cgit v1.2.2 From 69a43ac0cf40577157111bbe25500e2b98e801ea Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 20 Mar 2007 12:40:09 +0000 Subject: SAA9730: Fix large pile of warnings The SAA9730 driver doesn't quite grok what the difference between an ioport and memory mapped I/O is. It just happened to work on the one Linux system the SAA9730 happens to spend it's misserable existence on. drivers/net/saa9730.c: In function 'evm_saa9730_enable_lan_int': drivers/net/saa9730.c:68: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:70: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:72: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'evm_saa9730_disable_lan_int': drivers/net/saa9730.c:78: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:80: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'evm_saa9730_clear_lan_int': drivers/net/saa9730.c:85: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'evm_saa9730_block_lan_int': drivers/net/saa9730.c:91: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'evm_saa9730_unblock_lan_int': drivers/net/saa9730.c:97: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'show_saa9730_regs': drivers/net/saa9730.c:150: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_allocate_buffers': drivers/net/saa9730.c:292: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:295: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:302: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:305: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:312: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_cam_load': drivers/net/saa9730.c:329: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:332: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_mii_init': drivers/net/saa9730.c:369: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:395: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:403: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:410: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:432: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_control_init': drivers/net/saa9730.c:470: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:474: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:478: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:484: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:487: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:490: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:493: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_stop': drivers/net/saa9730.c:505: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:508: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:510: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_dma_init': drivers/net/saa9730.c:536: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_start': drivers/net/saa9730.c:556: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:560: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:564: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:567: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_tx': drivers/net/saa9730.c:590: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_rx': drivers/net/saa9730.c:664: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:729: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_write': drivers/net/saa9730.c:848: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c: In function 'lan_saa9730_set_multicast': drivers/net/saa9730.c:943: warning: passing argument 2 of 'outl' makes integer from pointer without a cast drivers/net/saa9730.c:949: warning: passing argument 2 of 'outl' makes integer from pointer without a cast Fixed by using writel instead of outl. 42 warnings less. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/saa9730.c | 177 +++++++++++++++++++++++++------------------------- 1 file changed, 88 insertions(+), 89 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c index b269513cde45..143958f1ef0a 100644 --- a/drivers/net/saa9730.c +++ b/drivers/net/saa9730.c @@ -64,37 +64,37 @@ static unsigned int pci_irq_line; static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); - outl(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptStatus1); - outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | - EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptStatus1); + writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | + EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); } static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); - outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptEnable1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptEnable1); } static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp) { - outl(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); + writel(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); } static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); } static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) { - outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, - &lp->evm_saa9730_regs->InterruptBlock1); + writel(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, + &lp->evm_saa9730_regs->InterruptBlock1); } static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) @@ -147,7 +147,7 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) printk("lp->lan_saa9730_regs->RxStatus = %x\n", readl(&lp->lan_saa9730_regs->RxStatus)); for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { - outl(i, &lp->lan_saa9730_regs->CamAddress); + writel(i, &lp->lan_saa9730_regs->CamAddress); printk("lp->lan_saa9730_regs->CamData = %x\n", readl(&lp->lan_saa9730_regs->CamData)); } @@ -288,28 +288,27 @@ static int lan_saa9730_allocate_buffers(struct pci_dev *pdev, * Set rx buffer A and rx buffer B to point to the first two buffer * spaces. */ - outl(lp->dma_addr + rxoffset, - &lp->lan_saa9730_regs->RxBuffA); - outl(lp->dma_addr + rxoffset + - LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE, - &lp->lan_saa9730_regs->RxBuffB); + writel(lp->dma_addr + rxoffset, &lp->lan_saa9730_regs->RxBuffA); + writel(lp->dma_addr + rxoffset + + LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE, + &lp->lan_saa9730_regs->RxBuffB); /* * Set txm_buf_a and txm_buf_b to point to the first two buffer * space */ - outl(lp->dma_addr + txoffset, - &lp->lan_saa9730_regs->TxBuffA); - outl(lp->dma_addr + txoffset + - LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE, - &lp->lan_saa9730_regs->TxBuffB); + writel(lp->dma_addr + txoffset, + &lp->lan_saa9730_regs->TxBuffA); + writel(lp->dma_addr + txoffset + + LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE, + &lp->lan_saa9730_regs->TxBuffB); /* Set packet number */ - outl((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | - (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | - (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | - (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), - &lp->lan_saa9730_regs->PacketCount); + writel((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | + (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | + (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | + (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), + &lp->lan_saa9730_regs->PacketCount); return 0; @@ -326,10 +325,10 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { /* First set address to where data is written */ - outl(i, &lp->lan_saa9730_regs->CamAddress); - outl((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) - | (NetworkAddress[2] << 8) | NetworkAddress[3], - &lp->lan_saa9730_regs->CamData); + writel(i, &lp->lan_saa9730_regs->CamAddress); + writel((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) | + (NetworkAddress[2] << 8) | NetworkAddress[3], + &lp->lan_saa9730_regs->CamData); NetworkAddress += 4; } return 0; @@ -365,8 +364,8 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) } /* Now set the control and address register. */ - outl(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, + &lp->lan_saa9730_regs->StationMgmtCtl); /* check link status, spin here till station is not busy */ i = 0; @@ -391,23 +390,23 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) /* Link is down, reset the PHY first. */ /* set PHY address = 'CONTROL' */ - outl(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, + &lp->lan_saa9730_regs->StationMgmtCtl); /* Wait for 1 ms. */ mdelay(1); /* set 'CONTROL' = force reset and renegotiate */ - outl(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | - PHY_CONTROL_RESTART_AUTO_NEG, - &lp->lan_saa9730_regs->StationMgmtData); + writel(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | + PHY_CONTROL_RESTART_AUTO_NEG, + &lp->lan_saa9730_regs->StationMgmtData); /* Wait for 50 ms. */ mdelay(50); /* set 'BUSY' to start operation */ - outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | - PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | + PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); /* await completion */ i = 0; @@ -427,9 +426,9 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) for (l = 0; l < 2; l++) { /* set PHY address = 'STATUS' */ - outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | - PHY_STATUS, - &lp->lan_saa9730_regs->StationMgmtCtl); + writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | + PHY_STATUS, + &lp->lan_saa9730_regs->StationMgmtCtl); /* await completion */ i = 0; @@ -462,35 +461,35 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) static int lan_saa9730_control_init(struct lan_saa9730_private *lp) { /* Initialize DMA control register. */ - outl((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | - (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | - (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) - | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | - DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN, - &lp->lan_saa9730_regs->LanDmaCtl); + writel((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | + (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | + (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) + | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | + DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN, + &lp->lan_saa9730_regs->LanDmaCtl); /* Initial MAC control register. */ - outl((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, - &lp->lan_saa9730_regs->MacCtl); + writel((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, + &lp->lan_saa9730_regs->MacCtl); /* Initialize CAM control register. */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); /* * Initialize CAM enable register, only turn on first entry, should * contain own addr. */ - outl(0x0001, &lp->lan_saa9730_regs->CamEnable); + writel(0x0001, &lp->lan_saa9730_regs->CamEnable); /* Initialize Tx control register */ - outl(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); + writel(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); /* Initialize Rcv control register */ - outl(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); + writel(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); /* Reset DMA engine */ - outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); + writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); return 0; } @@ -500,14 +499,14 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp) int i; /* Stop DMA first */ - outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) & - ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), - &lp->lan_saa9730_regs->LanDmaCtl); + writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) & + ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), + &lp->lan_saa9730_regs->LanDmaCtl); /* Set the SW Reset bits in DMA and MAC control registers */ - outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); - outl(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, - &lp->lan_saa9730_regs->MacCtl); + writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); + writel(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, + &lp->lan_saa9730_regs->MacCtl); /* * Wait for MAC reset to have finished. The reset bit is auto cleared @@ -532,8 +531,8 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp) /* Stop lan controller. */ lan_saa9730_stop(lp); - outl(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, - &lp->lan_saa9730_regs->Timeout); + writel(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, + &lp->lan_saa9730_regs->Timeout); return 0; } @@ -552,19 +551,19 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp) lp->PendingTxmPacketIndex = 0; lp->PendingTxmBufferIndex = 0; - outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | - DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); + writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | + DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); /* For Tx, turn on MAC then DMA */ - outl(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, - &lp->lan_saa9730_regs->TxCtl); + writel(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, + &lp->lan_saa9730_regs->TxCtl); /* For Rx, turn on DMA then MAC */ - outl(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, - &lp->lan_saa9730_regs->RxCtl); + writel(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, + &lp->lan_saa9730_regs->RxCtl); /* Set Ok2Use to let hardware own the buffers. */ - outl(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use); + writel(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use); return 0; } @@ -587,7 +586,7 @@ static int lan_saa9730_tx(struct net_device *dev) printk("lan_saa9730_tx interrupt\n"); /* Clear interrupt. */ - outl(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); + writel(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); while (1) { pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex] @@ -660,8 +659,8 @@ static int lan_saa9730_rx(struct net_device *dev) printk("lan_saa9730_rx interrupt\n"); /* Clear receive interrupts. */ - outl(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | - DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); + writel(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | + DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); /* Address next packet */ BufferIndex = lp->NextRcvBufferIndex; @@ -725,8 +724,8 @@ static int lan_saa9730_rx(struct net_device *dev) *pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF); /* Make sure A or B is available to hardware as appropriate. */ - outl(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A, - &lp->lan_saa9730_regs->Ok2Use); + writel(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A, + &lp->lan_saa9730_regs->Ok2Use); /* Go to next packet in sequence. */ lp->NextRcvPacketIndex++; @@ -844,8 +843,8 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, (len << TX_STAT_CTL_LENGTH_SHF)); /* Make sure A or B is available to hardware as appropriate. */ - outl(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A, - &lp->lan_saa9730_regs->Ok2Use); + writel(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A, + &lp->lan_saa9730_regs->Ok2Use); return 0; } @@ -938,15 +937,15 @@ static void lan_saa9730_set_multicast(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* accept all packets */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | - CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | + CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); } else { if (dev->flags & IFF_ALLMULTI) { /* accept all multicast packets */ - outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | - CAM_CONTROL_BROAD_ACC, - &lp->lan_saa9730_regs->CamCtl); + writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | + CAM_CONTROL_BROAD_ACC, + &lp->lan_saa9730_regs->CamCtl); } else { /* * Will handle the multicast stuff later. -carstenl -- cgit v1.2.2 From d57ab6fdde30816581f7b0a4fe3c015b3f41f9ca Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Tue, 20 Mar 2007 16:38:04 -0700 Subject: mv643xx_eth: add mv643xx_eth_shutdown function mv643xx_eth_shutdown is needed for kexec. Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 1ee27c360a4b..c9f55bc57edb 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1516,9 +1516,23 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) return 0; } +static void mv643xx_eth_shutdown(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct mv643xx_private *mp = netdev_priv(dev); + unsigned int port_num = mp->port_num; + + /* Mask all interrupts on ethernet port */ + mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0); + mv_read (MV643XX_ETH_INTERRUPT_MASK_REG(port_num)); + + eth_port_reset(port_num); +} + static struct platform_driver mv643xx_eth_driver = { .probe = mv643xx_eth_probe, .remove = mv643xx_eth_remove, + .shutdown = mv643xx_eth_shutdown, .driver = { .name = MV643XX_ETH_NAME, }, -- cgit v1.2.2 From aafa70eb56edd1cd5332c978bf9b5e224373c980 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 21 Mar 2007 19:45:18 +0100 Subject: myri10ge: Serverworks HT2100 provides aligned PCIe completion [PATCH 1/4] myri10ge: Serverworks HT2100 provides aligned PCIe completion Use the regular firmware on Serverworks HT2100 PCIe ports since this chipset provides aligned PCIe completion. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ac02b3b60f92..e7f9c088ebb5 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2483,6 +2483,8 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) #define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 #define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa +#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140 +#define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142 static void myri10ge_select_firmware(struct myri10ge_priv *mgp) { @@ -2514,6 +2516,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS && bridge->device == PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) + /* ServerWorks HT2100 */ + || (bridge->vendor == PCI_VENDOR_ID_SERVERWORKS + && bridge->device >= + PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST + && bridge->device <= + PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST) /* All Intel E5000 PCIE ports */ || (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device >= -- cgit v1.2.2 From f761fae1ae1e6e35ae15fce99d225d08d6cff1e7 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 21 Mar 2007 19:45:56 +0100 Subject: myri10ge: update wcfifo and intr_coal_delay default values Update the default value of 2 module parameters: * wcfifo disabled * intr_coal_delay 75us Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e7f9c088ebb5..2449b9fd7362 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -234,7 +234,7 @@ static int myri10ge_msi = 1; /* enable msi by default */ module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n"); -static int myri10ge_intr_coal_delay = 25; +static int myri10ge_intr_coal_delay = 75; module_param(myri10ge_intr_coal_delay, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n"); @@ -279,7 +279,7 @@ static int myri10ge_fill_thresh = 256; module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); -static int myri10ge_wcfifo = 1; +static int myri10ge_wcfifo = 0; module_param(myri10ge_wcfifo, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); -- cgit v1.2.2 From b52a8b7f0aeff5b91921cd53728ac781cdb4cccf Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 21 Mar 2007 19:46:57 +0100 Subject: myri10ge: fix management of >4kB allocated pages Fix management of allocated physical pages when the architecture page size is not 4kB since the firmware cannot cross 4K boundary. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 2449b9fd7362..c89ca3fec161 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -905,6 +905,14 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) { /* we can use part of previous page */ get_page(rx->page); +#if MYRI10GE_ALLOC_SIZE > 4096 + /* Firmware cannot cross 4K boundary.. */ + if ((rx->page_offset >> 12) != + ((rx->page_offset + bytes - 1) >> 12)) { + rx->page_offset = + (rx->page_offset + bytes) & ~4095; + } +#endif } else { /* we need a new page */ page = -- cgit v1.2.2 From 2ea34672f8cec20b22ccb6ba78e3fe61b44e734a Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 21 Mar 2007 19:47:32 +0100 Subject: myri10ge: update driver version to 1.3.0-1.226 Driver version is now 1.3.0-1.226. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c89ca3fec161..b05b20ef8c0a 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -71,7 +71,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.2.0" +#define MYRI10GE_VERSION_STR "1.3.0-1.226" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); -- cgit v1.2.2 From 194c1fbe43af532a7921d483bc2a553b2f361256 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Wed, 21 Mar 2007 19:21:00 -0700 Subject: cxgb3 - fix white spaces in drivers/net/Kconfig Use tabs instead of white spaces for CHELSIO_T3 entry. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1b6459b218ca..c3f9f599f134 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2372,23 +2372,23 @@ config CHELSIO_T1_NAPI when the driver is receiving lots of packets from the card. config CHELSIO_T3 - tristate "Chelsio Communications T3 10Gb Ethernet support" - depends on PCI + tristate "Chelsio Communications T3 10Gb Ethernet support" + depends on PCI select FW_LOADER - help - This driver supports Chelsio T3-based gigabit and 10Gb Ethernet - adapters. + help + This driver supports Chelsio T3-based gigabit and 10Gb Ethernet + adapters. - For general information about Chelsio and our products, visit - our website at . + For general information about Chelsio and our products, visit + our website at . - For customer support, please visit our customer support page at - . + For customer support, please visit our customer support page at + . - Please send feedback to . + Please send feedback to . - To compile this driver as a module, choose M here: the module - will be called cxgb3. + To compile this driver as a module, choose M here: the module + will be called cxgb3. config EHEA tristate "eHEA Ethernet support" -- cgit v1.2.2 From 991b5557f7f04602b3b161341dee85971e0b6be6 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 23 Mar 2007 02:03:29 -0400 Subject: [netdrvr] ewrk3: correct card detection bug Arwin Vosselman pointed out: > The ewrk3-driver doesn't function with 2.6.16-kernels (used 2.6.16.41 for > my tests). Cards will never be detected due to this bug. > > drivers/net/ewrks3.c: > Line 417 reads: > > if (nicsr == (CSR_TXD | CSR_RXD)) > > that should be: > > if (nicsr != (CSR_TXD | CSR_RXD)) > > Comparison with the same line in v2.4 shows why: > > 2.4: > if (nicsr == (CSR_TXD | CSR_RXD)){ > > blah, blah > ========== > 2.6: > if (nicsr == (CSR_TXD | CSR_RXD)) > return -ENXIO; > > blah, blah > ========== > > blah,blah will not, but should, be executed in 2.6 with a card being present. > > The fix mentioned above solves this bug. Signed-off-by: Jeff Garzik --- drivers/net/ewrk3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index c8c41f0a47d6..714ea1176ec7 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -414,10 +414,9 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) icr &= 0x70; outb(icr, EWRK3_ICR); /* Disable all the IRQs */ - if (nicsr == (CSR_TXD | CSR_RXD)) + if (nicsr != (CSR_TXD | CSR_RXD)) return -ENXIO; - /* Check that the EEPROM is alive and well and not living on Pluto... */ for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) { union { -- cgit v1.2.2 From 8fb303c7f1118b0a82aa08e33429adf9b5ad192c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 24 Mar 2007 14:26:13 +0000 Subject: [MIPS] SB1250: Fix bugs/warnings by creative use of volatile. Signed-off-by: Ralf Baechle --- drivers/net/sb1250-mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 1eae16b72b4b..103c3174ab54 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -243,7 +243,7 @@ struct sbmac_softc { * Controller-specific things */ - volatile void __iomem *sbm_base; /* MAC's base address */ + void __iomem *sbm_base; /* MAC's base address */ sbmac_state_t sbm_state; /* current state */ volatile void __iomem *sbm_macenable; /* MAC Enable Register */ -- cgit v1.2.2 From ea3d0d77086d2c2fbe73adcc1ad075ce1f5be0e0 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 22 Mar 2007 23:35:08 -0700 Subject: [NET]: remove unused header file: drivers/net/wan/lmc/lmc_media.h Signed-off-by: Robert P. J. Day Cc: Krzysztof Halasa Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/wan/lmc/lmc_media.h | 65 ----------------------------------------- 1 file changed, 65 deletions(-) delete mode 100644 drivers/net/wan/lmc/lmc_media.h (limited to 'drivers/net') diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h deleted file mode 100644 index ddcc00403563..000000000000 --- a/drivers/net/wan/lmc/lmc_media.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _LMC_MEDIA_H_ -#define _LMC_MEDIA_H_ - -lmc_media_t lmc_ds3_media = { - lmc_ds3_init, /* special media init stuff */ - lmc_ds3_default, /* reset to default state */ - lmc_ds3_set_status, /* reset status to state provided */ - lmc_dummy_set_1, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_ds3_set_100ft, /* set cable length */ - lmc_ds3_set_scram, /* set scrambler */ - lmc_ds3_get_link_status, /* get link status */ - lmc_dummy_set_1, /* set link status */ - lmc_ds3_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_ds3_watchdog -}; - -lmc_media_t lmc_hssi_media = { - lmc_hssi_init, /* special media init stuff */ - lmc_hssi_default, /* reset to default state */ - lmc_hssi_set_status, /* reset status to state provided */ - lmc_hssi_set_clock, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_hssi_get_link_status, /* get link status */ - lmc_hssi_set_link_status, /* set link status */ - lmc_hssi_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_hssi_watchdog -}; - -lmc_media_t lmc_ssi_media = { lmc_ssi_init, /* special media init stuff */ - lmc_ssi_default, /* reset to default state */ - lmc_ssi_set_status, /* reset status to state provided */ - lmc_ssi_set_clock, /* set clock source */ - lmc_ssi_set_speed, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_ssi_get_link_status, /* get link status */ - lmc_ssi_set_link_status, /* set link status */ - lmc_ssi_set_crc_length, /* set CRC length */ - lmc_dummy_set_1, /* set T1 or E1 circuit type */ - lmc_ssi_watchdog -}; - -lmc_media_t lmc_t1_media = { - lmc_t1_init, /* special media init stuff */ - lmc_t1_default, /* reset to default state */ - lmc_t1_set_status, /* reset status to state provided */ - lmc_t1_set_clock, /* set clock source */ - lmc_dummy_set2_1, /* set line speed */ - lmc_dummy_set_1, /* set cable length */ - lmc_dummy_set_1, /* set scrambler */ - lmc_t1_get_link_status, /* get link status */ - lmc_dummy_set_1, /* set link status */ - lmc_t1_set_crc_length, /* set CRC length */ - lmc_t1_set_circuit_type, /* set T1 or E1 circuit type */ - lmc_t1_watchdog -}; - - -#endif - -- cgit v1.2.2 From 1c46ae05d96f77f349ae60c799acb6ac6ddf07a8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 24 Mar 2007 20:54:37 -0700 Subject: [TG3]: Eliminate the unused TG3_FLAG_SPLIT_MODE flag. This flag to support multiple PCIX split completions was never used because of hardware bugs. This will make room for a new flag. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 17 +---------------- drivers/net/tg3.h | 4 ---- 2 files changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8c8f9f4d47a5..ab87bb1893a5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6321,8 +6321,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB | RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; /* If statement applies to 5705 and 5750 PCI devices only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && @@ -6495,9 +6493,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= (tp->split_mode_max_reqs << - PCIX_CAPS_SPLIT_SHIFT); } tw32(TG3PCI_X_CAPS, val); } @@ -10863,14 +10858,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; - /* Broadcom's driver says that CIOBE multisplit has a bug */ -#if 0 - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { - tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; - tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; - } -#endif if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) @@ -11968,14 +11955,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, i == 5 ? '\n' : ':'); printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " - "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] " - "TSOcap[%d] \n", + "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n", dev->name, (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, - (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n", diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 086892d8c1f1..5df8f76cdfe7 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2223,7 +2223,6 @@ struct tg3 { #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 -#define TG3_FLAG_SPLIT_MODE 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 @@ -2262,9 +2261,6 @@ struct tg3 { #define TG3_FLG2_NO_FWARE_REPORTED 0x40000000 #define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000 - u32 split_mode_max_reqs; -#define SPLIT_MODE_5704_MAX_REQ 3 - struct timer_list timer; u16 timer_counter; u16 timer_multiplier; -- cgit v1.2.2 From d18edcb212d7dc864a59e6aa9b6b9826299e0210 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 24 Mar 2007 20:57:11 -0700 Subject: [TG3]: Exit irq handler during chip reset. On most tg3 chips, the memory enable bit in the PCI command register gets cleared during chip reset and must be restored before accessing PCI registers using memory cycles. The chip does not generate interrupt during chip reset, but the irq handler can still be called because of irq sharing or irqpoll. Reading a register in the irq handler can cause a master abort in this scenario and may result in a crash on some architectures. Use the TG3_FLAG_CHIP_RESETTING flag to tell the irq handler to exit without touching any registers. The checking of the flag is in the "slow" path of the irq handler and will not affect normal performance. The msi handler is not shared and therefore does not require checking the flag. Thanks to Bernhard Walle for reporting the problem. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 113 +++++++++++++++++++++++++++++++----------------------- drivers/net/tg3.h | 1 + 2 files changed, 67 insertions(+), 47 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ab87bb1893a5..26dcd1c36b30 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3568,32 +3568,34 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if ((sblk->status & SD_STATUS_UPDATED) || - !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - /* - * Writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * Writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - if (tg3_irq_sync(tp)) + if (unlikely(!(sblk->status & SD_STATUS_UPDATED))) { + if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { + handled = 0; goto out; - sblk->status &= ~SD_STATUS_UPDATED; - if (likely(tg3_has_work(tp))) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - netif_rx_schedule(dev); /* schedule NAPI poll */ - } else { - /* No work, shared interrupt perhaps? re-enable - * interrupts, and flush that PCI write - */ - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); } - } else { /* shared interrupt */ - handled = 0; + } + + /* + * Writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. + * Writing non-zero to intr-mbox-0 additional tells the + * NIC to stop sending us irqs, engaging "in-intr-handler" + * event coalescing. + */ + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + if (tg3_irq_sync(tp)) + goto out; + sblk->status &= ~SD_STATUS_UPDATED; + if (likely(tg3_has_work(tp))) { + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + netif_rx_schedule(dev); /* schedule NAPI poll */ + } else { + /* No work, shared interrupt perhaps? re-enable + * interrupts, and flush that PCI write + */ + tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + 0x00000000); } out: return IRQ_RETVAL(handled); @@ -3611,31 +3613,33 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if ((sblk->status_tag != tp->last_tag) || - !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { - /* - * writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - if (tg3_irq_sync(tp)) + if (unlikely(sblk->status_tag == tp->last_tag)) { + if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || + (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { + handled = 0; goto out; - if (netif_rx_schedule_prep(dev)) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - /* Update last_tag to mark that this status has been - * seen. Because interrupt may be shared, we may be - * racing with tg3_poll(), so only update last_tag - * if tg3_poll() is not scheduled. - */ - tp->last_tag = sblk->status_tag; - __netif_rx_schedule(dev); } - } else { /* shared interrupt */ - handled = 0; + } + + /* + * writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. + * writing non-zero to intr-mbox-0 additional tells the + * NIC to stop sending us irqs, engaging "in-intr-handler" + * event coalescing. + */ + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + if (tg3_irq_sync(tp)) + goto out; + if (netif_rx_schedule_prep(dev)) { + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + /* Update last_tag to mark that this status has been + * seen. Because interrupt may be shared, we may be + * racing with tg3_poll(), so only update last_tag + * if tg3_poll() is not scheduled. + */ + tp->last_tag = sblk->status_tag; + __netif_rx_schedule(dev); } out: return IRQ_RETVAL(handled); @@ -4823,6 +4827,19 @@ static int tg3_chip_reset(struct tg3 *tp) if (write_op == tg3_write_flush_reg32) tp->write32 = tg3_write32; + /* Prevent the irq handler from reading or writing PCI registers + * during chip reset when the memory enable bit in the PCI command + * register may be cleared. The chip does not generate interrupt + * at this time, but the irq handler may still be called due to irq + * sharing or irqpoll. + */ + tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING; + tp->hw_status->status = 0; + tp->hw_status->status_tag = 0; + tp->last_tag = 0; + smp_mb(); + synchronize_irq(tp->pdev->irq); + /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; @@ -4904,6 +4921,8 @@ static int tg3_chip_reset(struct tg3 *tp) pci_restore_state(tp->pdev); + tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; + /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); val &= ~PCIX_CAPS_RELAXED_ORDERING; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 5df8f76cdfe7..d515ed23841b 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2223,6 +2223,7 @@ struct tg3 { #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 +#define TG3_FLAG_CHIP_RESETTING 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 -- cgit v1.2.2 From 20bd7dd4cabfd0d6b6b70b99e88df901480a9841 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 24 Mar 2007 20:58:51 -0700 Subject: [TG3]: Update version and reldate. Update version to 3.75. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 26dcd1c36b30..0acee9f324e9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.74" -#define DRV_MODULE_RELDATE "February 20, 2007" +#define DRV_MODULE_VERSION "3.75" +#define DRV_MODULE_RELDATE "March 23, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.2 From 165de5b7f2719c1984956504128545839762d635 Mon Sep 17 00:00:00 2001 From: "G. Liakhovetski" Date: Sun, 25 Mar 2007 19:04:09 -0700 Subject: [PPP]: Don't leak an sk_buff on interface destruction. Signed-off-by: G. Liakhovetski Acked-by: Paul Mackerras Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 11b575f89856..ef58e4128782 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2544,6 +2544,9 @@ static void ppp_destroy_interface(struct ppp *ppp) ppp->active_filter = NULL; #endif /* CONFIG_PPP_FILTER */ + if (ppp->xmit_pending) + kfree_skb(ppp->xmit_pending); + kfree(ppp); } -- cgit v1.2.2 From 09c72ec8ed8f7499d115309a6e19cd5e66808d88 Mon Sep 17 00:00:00 2001 From: Ruben Vandeginste Date: Mon, 26 Mar 2007 14:43:49 -0700 Subject: [SUNGEM]: Fix MAC address setting when interface is up. This patch implements set_mac_address for the sungem driver. This allows changing the mac address of the interface, even when the interface is up. Signed-off-by: Ruben Vandeginste Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David S. Miller --- drivers/net/sungem.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 616be8d0fa85..08ea61db46fe 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2530,6 +2530,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev) return &gp->net_stats; } +static int gem_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *macaddr = (struct sockaddr *) addr; + struct gem *gp = dev->priv; + unsigned char *e = &dev->dev_addr[0]; + + if (!is_valid_ether_addr(macaddr->sa_data)) + return -EADDRNOTAVAIL; + + if (!netif_running(dev) || !netif_device_present(dev)) { + /* We'll just catch it later when the + * device is up'd or resumed. + */ + memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len); + return 0; + } + + mutex_lock(&gp->pm_mutex); + memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len); + if (gp->running) { + writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0); + writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1); + writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2); + } + mutex_unlock(&gp->pm_mutex); + + return 0; +} + static void gem_set_multicast(struct net_device *dev) { struct gem *gp = dev->priv; @@ -3122,6 +3151,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->change_mtu = gem_change_mtu; dev->irq = pdev->irq; dev->dma = 0; + dev->set_mac_address = gem_set_mac_address; #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = gem_poll_controller; #endif -- cgit v1.2.2 From be10d3860ef07ff43f240fbc0c0b72df1a5fe3df Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 17 Mar 2007 11:28:21 -0500 Subject: [PATCH] bcm43xx: Fix code for confusion between PHY revision and PHY version There are several places where the PHY version and revision were interchanged. These are changed in the specifications on 2/13/07 and now use "analog" instead instead of "version" to help reduce confusion. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index ee1e7a2afc08..d87a22825b46 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -458,7 +458,7 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0x0810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->rev == 0) { + if (phy->analog == 0) { bcm43xx_phy_write(bcm, 0x0003, 0x0122); } else { bcm43xx_phy_write(bcm, 0x000A, @@ -570,9 +570,9 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_write16(bcm, 0x03E6, 0x0040); - } else if (phy->rev == 0) { + } else if (phy->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, @@ -596,7 +596,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0015, backup[5]); bcm43xx_phy_write(bcm, 0x002A, backup[6]); bcm43xx_synth_pu_workaround(bcm, radio->channel); - if (phy->rev != 0) + if (phy->analog != 0) bcm43xx_write16(bcm, 0x03F4, backup[13]); bcm43xx_phy_write(bcm, 0x0020, backup[7]); @@ -692,7 +692,7 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->rev >= 2) { + if (phy->analog >= 2) { bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); -- cgit v1.2.2 From 7265c5d10dd893b91aab15735ed9346a0e07bf07 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 23 Mar 2007 20:21:39 +0100 Subject: [PATCH] bcm43xx: fix radio_set_tx_iq Fix a duplicated leftshift in bcm43xx_radio_set_tx_iq. data_high values are already leftshifted. Thanks to Michael Buesch for spotting this. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index d87a22825b46..4025dd0089d2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1579,7 +1579,7 @@ void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] << 4 | data_low[j])) { + if (tmp == (data_high[i] | data_low[j])) { bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); return; } -- cgit v1.2.2 From 83b5db89c851f9a2080e2e43427346269ab84447 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 25 Mar 2007 08:45:54 -0500 Subject: [PATCH] bcm43xx: Fix machine check on PPC for version 1 PHY Recent changes in the specs that were introduced in commit 740ac4fb08866d702be90f167665d03759bd27d0 were incorrect and resulted in machine check errors on the PPC architecture for G PHY's with a revision number equal to 1. The two offending changes are reverted. Signed-off-by: David Woodhouse Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index cae89258a640..d1e89be965cd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -757,7 +757,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) if (radio->version == 0x2050) bcm43xx_phy_write(bcm, 0x0038, 0x0667); - if (phy->type == BCM43xx_PHYTYPE_G) { + if (phy->connected) { if (radio->version == 0x2050) { bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) @@ -1192,7 +1192,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); } - if (phy->connected) { + if (phy->rev >= 2 && phy->connected) { tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; if (tmp < 6) { bcm43xx_phy_write(bcm, 0x04C2, 0x1816); -- cgit v1.2.2 From 917690cd035b422b1ac933ac160d26016aa454ac Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 27 Mar 2007 21:54:53 +0200 Subject: myri10ge: correctly detect when TSO should be used Correctly detect when TSO should be used on transmit by looking at the skb->gso_size rather than seeing if the frame was larger than our MTU. The old method causes problems when a host with a large (jumbo) MTU is sending to a host with a small (standard) MTU. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b05b20ef8c0a..c216e6a5d235 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -71,7 +71,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.0-1.226" +#define MYRI10GE_VERSION_STR "1.3.0-1.227" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -2015,10 +2015,9 @@ again: mss = 0; max_segments = MXGEFW_MAX_SEND_DESC; - if (skb->len > (dev->mtu + ETH_HLEN)) { + if (skb_is_gso(skb)) { mss = skb_shinfo(skb)->gso_size; - if (mss != 0) - max_segments = MYRI10GE_MAX_SEND_DESC_TSO; + max_segments = MYRI10GE_MAX_SEND_DESC_TSO; } if ((unlikely(avail < max_segments))) { -- cgit v1.2.2 From de815a14e9d03df0560e6ef689d1da32553878b7 Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Tue, 27 Mar 2007 19:43:49 -0500 Subject: atl1: remove unnecessary crc inversion The original vendor driver contained a private ether_crc_le() function that produced an inverted crc. When we changed to the kernel version of ether_crc_le(), we neglected to undo the inversion. Let's do it now. Discovered by and patch proffered by Jose Alberto Reguero. Signed-off-by: Jose Alberto Reguero Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atl1/atl1_hw.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c index 314dbaabb642..69482e0d849b 100644 --- a/drivers/net/atl1/atl1_hw.c +++ b/drivers/net/atl1/atl1_hw.c @@ -334,7 +334,6 @@ u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr) int i; crc32 = ether_crc_le(6, mc_addr); - crc32 = ~crc32; for (i = 0; i < 32; i++) value |= (((crc32 >> i) & 1) << (31 - i)); -- cgit v1.2.2 From d8a759ff414141c8a0f6683e9f35b895b5f23b57 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 26 Mar 2007 13:42:57 -0700 Subject: qla3xxx: bugfix: Add tx control block memset. This was removed in a previous patch to increase performance, but caused a transmit error for the 4032 chip. Signed-off-by: Ron Mercer Signed-off-by: Jeff Garzik --- drivers/net/qla3xxx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index d3f65dab306c..5d358d3779de 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2380,6 +2380,7 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) } mac_iocb_ptr = tx_cb->queue_entry; + memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req)); mac_iocb_ptr->opcode = qdev->mac_ob_opcode; mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X; mac_iocb_ptr->flags |= qdev->mb_bit_mask; -- cgit v1.2.2 From b6967eb9cbf38643fc1b5432c36f610a9c565579 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 26 Mar 2007 13:42:58 -0700 Subject: qla3xxx: bugfix: Multi segment sends were getting whacked. The proper header length was not being used. Signed-off-by: Ron Mercer Signed-off-by: Jeff Garzik --- drivers/net/qla3xxx.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 5d358d3779de..9952e3931e34 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2217,12 +2217,7 @@ static int ql_send_map(struct ql3_adapter *qdev, int seg_cnt, seg = 0; int frag_cnt = (int)skb_shinfo(skb)->nr_frags; - seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev, - (skb_shinfo(skb)->nr_frags)); - if(seg_cnt == -1) { - printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__); - return NETDEV_TX_BUSY; - } + seg_cnt = tx_cb->seg_count; /* * Map the skb buffer first. */ @@ -2278,7 +2273,7 @@ static int ql_send_map(struct ql3_adapter *qdev, pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); pci_unmap_len_set(&tx_cb->map[seg], maplen, - len); + sizeof(struct oal)); oal_entry = (struct oal_entry *)oal; oal++; seg++; -- cgit v1.2.2 From f67cac0190623a3cde4d783c7c7205691aa02cc2 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 26 Mar 2007 13:42:59 -0700 Subject: qla3xxx: bugfix: Dropping interrupt under heavy network load. Update the rx queue pointer when exiting NAPI poll rather than at the end of each iteration. Remove unnecessary PCI flushes that occurred after every write. Now write all regs and flush once. Signed-off-by: Ron Mercer Signed-off-by: Jeff Garzik --- drivers/net/qla3xxx.c | 71 ++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 41 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 9952e3931e34..6612936306d7 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1688,6 +1688,27 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) return 0; } +/* + * Caller holds hw_lock. + */ +static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev) +{ + struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; + if (qdev->small_buf_release_cnt >= 16) { + while (qdev->small_buf_release_cnt >= 16) { + qdev->small_buf_q_producer_index++; + + if (qdev->small_buf_q_producer_index == + NUM_SBUFQ_ENTRIES) + qdev->small_buf_q_producer_index = 0; + qdev->small_buf_release_cnt -= 8; + } + wmb(); + writel(qdev->small_buf_q_producer_index, + &port_regs->CommonRegs.rxSmallQProducerIndex); + } +} + /* * Caller holds hw_lock. */ @@ -1732,13 +1753,10 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev) lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr; } } - + wmb(); qdev->lrg_buf_next_free = lrg_buf_q_ele; - - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxLargeQProducerIndex, - qdev->lrg_buf_q_producer_index); + writel(qdev->lrg_buf_q_producer_index, + &port_regs->CommonRegs.rxLargeQProducerIndex); } } @@ -1944,16 +1962,12 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, static int ql_tx_rx_clean(struct ql3_adapter *qdev, int *tx_cleaned, int *rx_cleaned, int work_to_do) { - struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct net_rsp_iocb *net_rsp; struct net_device *ndev = qdev->ndev; - unsigned long hw_flags; int work_done = 0; - u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index)); - /* While there are entries in the completion queue. */ - while ((rsp_producer_index != + while ((le32_to_cpu(*(qdev->prsp_producer_index)) != qdev->rsp_consumer_index) && (work_done < work_to_do)) { net_rsp = qdev->rsp_current; @@ -2009,33 +2023,7 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, work_done = *tx_cleaned + *rx_cleaned; } - if(work_done) { - spin_lock_irqsave(&qdev->hw_lock, hw_flags); - - ql_update_lrg_bufq_prod_index(qdev); - - if (qdev->small_buf_release_cnt >= 16) { - while (qdev->small_buf_release_cnt >= 16) { - qdev->small_buf_q_producer_index++; - - if (qdev->small_buf_q_producer_index == - NUM_SBUFQ_ENTRIES) - qdev->small_buf_q_producer_index = 0; - qdev->small_buf_release_cnt -= 8; - } - - wmb(); - ql_write_common_reg(qdev, - &port_regs->CommonRegs. - rxSmallQProducerIndex, - qdev->small_buf_q_producer_index); - - } - - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); - } - - return *tx_cleaned + *rx_cleaned; + return work_done; } static int ql_poll(struct net_device *ndev, int *budget) @@ -2059,9 +2047,10 @@ quit_polling: netif_rx_complete(ndev); spin_lock_irqsave(&qdev->hw_lock, hw_flags); - ql_write_common_reg(qdev, - &port_regs->CommonRegs.rspQConsumerIndex, - qdev->rsp_consumer_index); + ql_update_small_bufq_prod_index(qdev); + ql_update_lrg_bufq_prod_index(qdev); + writel(qdev->rsp_consumer_index, + &port_regs->CommonRegs.rspQConsumerIndex); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); ql_enable_interrupts(qdev); -- cgit v1.2.2 From b3b1514c90ab534ec6c9e4452953069f85aacf4d Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 26 Mar 2007 13:43:00 -0700 Subject: qla3xxx: bugfix: Jumbo frame handling. Fixed rx checksum bits. Turn on TCP processing for rx checksum. Fixed max frame length register write. It wasn't getting set in multi-port system. Set rx buffer queue length properly for jumbo frames. Signed-off-by: Ron Mercer Signed-off-by: Jeff Garzik --- drivers/net/qla3xxx.c | 29 +++++++++++++++-------------- drivers/net/qla3xxx.h | 3 +-- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 6612936306d7..a8246eb2f8d9 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1933,17 +1933,18 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum); if (checksum & (IB_IP_IOCB_RSP_3032_ICE | - IB_IP_IOCB_RSP_3032_CE | - IB_IP_IOCB_RSP_3032_NUC)) { + IB_IP_IOCB_RSP_3032_CE)) { printk(KERN_ERR "%s: Bad checksum for this %s packet, checksum = %x.\n", __func__, ((checksum & IB_IP_IOCB_RSP_3032_TCP) ? "TCP" : "UDP"),checksum); - } else if (checksum & IB_IP_IOCB_RSP_3032_TCP) { + } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) || + (checksum & IB_IP_IOCB_RSP_3032_UDP && + !(checksum & IB_IP_IOCB_RSP_3032_NUC))) { skb2->ip_summed = CHECKSUM_UNNECESSARY; - } + } } skb2->dev = qdev->ndev; skb2->protocol = eth_type_trans(skb2, qdev->ndev); @@ -3039,15 +3040,6 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) goto out; } - if (qdev->mac_index) - ql_write_page0_reg(qdev, - &port_regs->mac1MaxFrameLengthReg, - qdev->max_frame_size); - else - ql_write_page0_reg(qdev, - &port_regs->mac0MaxFrameLengthReg, - qdev->max_frame_size); - value = qdev->nvram_data.tcpMaxWindowSize; ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value); @@ -3067,6 +3059,14 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) ql_sem_unlock(qdev, QL_FLASH_SEM_MASK); } + if (qdev->mac_index) + ql_write_page0_reg(qdev, + &port_regs->mac1MaxFrameLengthReg, + qdev->max_frame_size); + else + ql_write_page0_reg(qdev, + &port_regs->mac0MaxFrameLengthReg, + qdev->max_frame_size); if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * @@ -3137,7 +3137,8 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) if (qdev->device_id == QL3032_DEVICE_ID) { value = (QL3032_PORT_CONTROL_EF | QL3032_PORT_CONTROL_KIE | - QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4); + QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4 | + QL3032_PORT_CONTROL_ET); ql_write_page0_reg(qdev, &port_regs->functionControl, ((value << 16) | value)); } else { diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 34cd6580fd07..0203f88f0544 100755 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1014,8 +1014,7 @@ struct eeprom_data { /* Transmit and Receive Buffers */ #define NUM_LBUFQ_ENTRIES 128 -#define JUMBO_NUM_LBUFQ_ENTRIES \ -(NUM_LBUFQ_ENTRIES/(JUMBO_MTU_SIZE/NORMAL_MTU_SIZE)) +#define JUMBO_NUM_LBUFQ_ENTRIES 32 #define NUM_SBUFQ_ENTRIES 64 #define QL_SMALL_BUFFER_SIZE 32 #define QL_ADDR_ELE_PER_BUFQ_ENTRY \ -- cgit v1.2.2 From fcc5f2665c81e087fb95143325ed769a41128d50 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 23 Mar 2007 05:49:37 -0500 Subject: forcedeth: fix nic poll The nic poll routine was missing the call to the optimized irq routine. This patch adds the missing call for the optimized path. See http://bugzilla.kernel.org/show_bug.cgi?id=7950 for more information. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 46e1697d9cfd..ae4e6f9375c8 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3536,7 +3536,10 @@ static void nv_do_nic_poll(unsigned long data) pci_push(base); if (!using_multi_irqs(dev)) { - nv_nic_irq(0, dev); + if (np->desc_ver == DESC_VER_3) + nv_nic_irq_optimized(0, dev); + else + nv_nic_irq(0, dev); if (np->msi_flags & NV_MSI_X_ENABLED) enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); else -- cgit v1.2.2 From 3ba4d093fe8a26f5f2da94411bf8732fa6e9da86 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 23 Mar 2007 05:50:02 -0500 Subject: forcedeth: fix tx timeout The tx timeout routine was waking the tx queue conditionally. However, it must call it unconditionally since the dev_watchdog has halted the tx queue before calling the timeout function. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index ae4e6f9375c8..d04214e4e581 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2050,9 +2050,10 @@ static void nv_tx_timeout(struct net_device *dev) nv_drain_tx(dev); nv_init_tx(dev); setup_hw_rings(dev, NV_SETUP_TX_RING); - netif_wake_queue(dev); } + netif_wake_queue(dev); + /* 4) restart tx engine */ nv_start_tx(dev); spin_unlock_irq(&np->lock); -- cgit v1.2.2 From fadac4060c0456ce0a190ee581746ae8663f84e1 Mon Sep 17 00:00:00 2001 From: Gabriel Paubert Date: Fri, 23 Mar 2007 12:03:52 -0700 Subject: mv643xx_eth: Fix use of uninitialized port_num field In this driver, the default ethernet address is first set by by calling eth_port_uc_addr_get() which reads the relevant registers of the corresponding port as initially set by firmware. However that function used the port_num field accessed through the private area of net_dev before it was set. The result was that one board I have ended up with the unicast address set to 00:00:00:00:00:00 (only port 1 is connected on this board). The problem appeared after commit 84dd619e4dc3b0b1c40dafd98c90fd950bce7bc5. This patch fixes the bug by setting mp->port_num prior to calling eth_port_uc_get_addr(). Signed-off-by: Gabriel Paubert Signed-off-by: Dale Farnsworth Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index c9f55bc57edb..8015a7c5b0c9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1379,7 +1379,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) spin_lock_init(&mp->lock); - port_num = pd->port_number; + port_num = mp->port_num = pd->port_number; /* set default config values */ eth_port_uc_addr_get(dev, dev->dev_addr); @@ -1411,8 +1411,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) duplex = pd->duplex; speed = pd->speed; - mp->port_num = port_num; - /* Hook up MII support for ethtool */ mp->mii.dev = dev; mp->mii.mdio_read = mv643xx_mdio_read; -- cgit v1.2.2 From c14bac628b9fad6fd4dad8fbb9e864c61a8924c9 Mon Sep 17 00:00:00 2001 From: "Cyrill V. Gorcunov" Date: Mon, 26 Mar 2007 21:47:26 -0800 Subject: SUN3/3X Lance trivial fix improved This patch adds checking for allocated DVMA memory and granted IRQ line. Signed-off-by: Cyrill V. Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sun3lance.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index c62e85d89f41..7bee45b42a2c 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -336,13 +336,27 @@ static int __init lance_probe( struct net_device *dev) /* XXX - leak? */ MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000); + if (MEM == NULL) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + printk(KERN_WARNING "SUN3 Lance couldn't allocate DVMA memory\n"); + return 0; + } lp->iobase = (volatile unsigned short *)ioaddr; dev->base_addr = (unsigned long)ioaddr; /* informational only */ REGA(CSR0) = CSR0_STOP; - request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev); + if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + dvma_free((void *)MEM); + printk(KERN_WARNING "SUN3 Lance unable to allocate IRQ\n"); + return 0; + } dev->irq = (unsigned short)LANCE_IRQ; -- cgit v1.2.2 From db8b22550d4b83f0910d27a34d05aa16f7f7159f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 28 Mar 2007 14:17:36 -0700 Subject: [BNX2]: Fix link interrupt problem. bnx2_has_work()'s logic is flawed and can cause the driver to miss a link event. The fix is to compare the status block's attn_bits and attn_bits_ack to determine if there is a link event. Update version to 1.5.6. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c12e5ea61819..d43fe2863095 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.5" -#define DRV_MODULE_RELDATE "February 1, 2007" +#define DRV_MODULE_VERSION "1.5.6" +#define DRV_MODULE_RELDATE "March 28, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -2033,8 +2033,8 @@ bnx2_has_work(struct bnx2 *bp) (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) return 1; - if (((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) != - bp->link_up) + if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != + (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) return 1; return 0; -- cgit v1.2.2 From 8c754a04ff11a9c1107c134ad5a858e9dc08c1de Mon Sep 17 00:00:00 2001 From: Chris Snook Date: Wed, 28 Mar 2007 20:51:51 -0400 Subject: atl1: save mac address on remove Some atl1 boards get their MAC address written directly to the register by the BIOS during POST, rather than storing it in EEPROM that's accessible to the driver. If the MAC register on one of these boards is changed and then the module is unloaded, the permanent MAC address will be forgotten until the box is rebooted. We should save the permanent address during removal if we've been messing with it. Signed-off-by: Chris Snook Signed-off-by: Jeff Garzik --- drivers/net/atl1/atl1_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index dee3638ad744..8606eac5bec8 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -2320,6 +2320,16 @@ static void __devexit atl1_remove(struct pci_dev *pdev) return; adapter = netdev_priv(netdev); + + /* Some atl1 boards lack persistent storage for their MAC, and get it + * from the BIOS during POST. If we've been messing with the MAC + * address, we need to save the permanent one. + */ + if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { + memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN); + atl1_set_mac_addr(&adapter->hw); + } + iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE); unregister_netdev(netdev); pci_iounmap(pdev, adapter->hw.hw_addr); -- cgit v1.2.2 From bd7a44488975759da10b5f25bcebec19930a5328 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 29 Mar 2007 00:18:50 +0200 Subject: sis190: new PHY support Reported to work on the WinFast 761GXK8MB-RS motherboard. Plain 10/100 Mbps. Signed-off-by: Paul Gibbons Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/sis190.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b08508b35833..34463ce6f132 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -324,6 +324,7 @@ static struct mii_chip_info { u32 feature; } mii_chip_table[] = { { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 }, + { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 }, { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 }, { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 }, { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 }, -- cgit v1.2.2 From d8d79201eb391ae0eca05f9e51f1f94ab42b6b4e Mon Sep 17 00:00:00 2001 From: Linsys Contractor Adhiraj Joshi Date: Fri, 23 Mar 2007 07:21:24 -0800 Subject: NetXen: Fix hardware access for ppc architecture. NetXen: Fix for hardware access on big endian machine. Signed-off-by: Adhiraj Joshi Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 229aa1c4fb79..eff965dc5fff 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -438,6 +438,7 @@ do_rom_fast_read_words(struct netxen_adapter *adapter, int addr, for (addridx = addr; addridx < (addr + size); addridx += 4) { ret = do_rom_fast_read(adapter, addridx, (int *)bytes); + *(int *)bytes = cpu_to_le32(*(int *)bytes); if (ret != 0) break; bytes += 4; @@ -497,7 +498,7 @@ static inline int do_rom_fast_write_words(struct netxen_adapter *adapter, int timeout = 0; int data; - data = *(u32*)bytes; + data = le32_to_cpu((*(u32*)bytes)); ret = do_rom_fast_write(adapter, addridx, data); if (ret < 0) -- cgit v1.2.2 From c01003c20563d1e75ec9828d21743919d2b43977 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 29 Mar 2007 11:46:52 -0700 Subject: [IFB]: Fix crash on input device removal The input_device pointer is not refcounted, which means the device may disappear while packets are queued, causing a crash when ifb passes packets with a stale skb->dev pointer to netif_rx(). Fix by storing the interface index instead and do a lookup where neccessary. Signed-off-by: Patrick McHardy Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- drivers/net/ifb.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index ca2b21f9d444..07b4c0d7a75c 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -96,17 +96,24 @@ static void ri_tasklet(unsigned long dev) skb->tc_verd = SET_TC_NCLS(skb->tc_verd); stats->tx_packets++; stats->tx_bytes +=skb->len; + + skb->dev = __dev_get_by_index(skb->iif); + if (!skb->dev) { + dev_kfree_skb(skb); + stats->tx_dropped++; + break; + } + skb->iif = _dev->ifindex; + if (from & AT_EGRESS) { dp->st_rx_frm_egr++; dev_queue_xmit(skb); } else if (from & AT_INGRESS) { - dp->st_rx_frm_ing++; + skb_pull(skb, skb->dev->hard_header_len); netif_rx(skb); - } else { - dev_kfree_skb(skb); - stats->tx_dropped++; - } + } else + BUG(); } if (netif_tx_trylock(_dev)) { @@ -157,26 +164,10 @@ static int ifb_xmit(struct sk_buff *skb, struct net_device *dev) stats->rx_packets++; stats->rx_bytes+=skb->len; - if (!from || !skb->input_dev) { -dropped: + if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->iif) { dev_kfree_skb(skb); stats->rx_dropped++; return ret; - } else { - /* - * note we could be going - * ingress -> egress or - * egress -> ingress - */ - skb->dev = skb->input_dev; - skb->input_dev = dev; - if (from & AT_INGRESS) { - skb_pull(skb, skb->dev->hard_header_len); - } else { - if (!(from & AT_EGRESS)) { - goto dropped; - } - } } if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) { -- cgit v1.2.2 From 9a4d93d49d140c196020a1bae339efcf211cac03 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 30 Mar 2007 08:49:55 +0100 Subject: [ARM] 4295/2: Fix error-handling in pxaficp_ir.c (version 2) This patch addresses the following issues with the pxa2xx FIr driver: 1. increment overrun error counter and not frame error counter on ICSR1_ROR bit set in ICSR1. 2. drop frames reported with the frame error from the IC. 3. when resetting the receiver and preparing it for the next DMA in pxa_irda_fir_irq() actually clear the Rx FIFO. See description in Table 11-2 in PXA270 Developer's Manual of the RXE bit. Correction added in version 2: clearing the IC Rx FIFO also has to be done in pxa_irda_fir_dma_tx_irq() Signed-off-by: G. Liakhovetski Signed-off-by: Russell King --- drivers/net/irda/pxaficp_ir.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 9137e239fac2..2272156af31e 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -321,15 +321,22 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) pxa_irda_set_speed(si, si->newspeed); si->newspeed = 0; } else { + int i = 64; + ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); + while ((ICSR1 & ICSR1_RNE) && i--) + (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; + + if (i < 0) + printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); } netif_wake_queue(dev); } /* EIF(Error in FIFO/End in Frame) handler for FIR */ -static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) +static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0) { unsigned int len, stat, data; @@ -350,7 +357,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) } if (stat & ICSR1_ROR) { printk(KERN_DEBUG "pxa_ir: fir receive overrun\n"); - si->stats.rx_frame_errors++; + si->stats.rx_over_errors++; } } else { si->dma_rx_buff[len++] = data; @@ -362,7 +369,15 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) if (stat & ICSR1_EOF) { /* end of frame. */ - struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC); + struct sk_buff *skb; + + if (icsr0 & ICSR0_FRE) { + printk(KERN_ERR "pxa_ir: dropping erroneous frame\n"); + si->stats.rx_dropped++; + return; + } + + skb = alloc_skb(len+1,GFP_ATOMIC); if (!skb) { printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n"); si->stats.rx_dropped++; @@ -392,7 +407,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) { struct net_device *dev = dev_id; struct pxa_irda *si = netdev_priv(dev); - int icsr0; + int icsr0, i = 64; /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; @@ -412,13 +427,18 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) if (icsr0 & ICSR0_EIF) { /* An error in FIFO occured, or there is a end of frame */ - pxa_irda_fir_irq_eif(si, dev); + pxa_irda_fir_irq_eif(si, dev, icsr0); } ICCR0 = 0; pxa_irda_fir_dma_rx_start(si); + while ((ICSR1 & ICSR1_RNE) && i--) + (void)ICDR; ICCR0 = ICCR0_ITR | ICCR0_RXE; + if (i < 0) + printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); + return IRQ_HANDLED; } -- cgit v1.2.2 From c873879c4db31bab414655e191cf56019b48c751 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 30 Mar 2007 14:53:06 -0700 Subject: [BNX2]: Fix nvram write logic. The nvram dword alignment logic was broken when writing less than 4 bytes on a non-aligned offset. It was missing logic to round the length to 4 bytes. The page erase code is also moved so that it is only called when using non-buffered flash for better code clarity. Update version to 1.5.7. Based on initial patch from Tony Cureington . Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d43fe2863095..0b7aded8dcfd 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.6" -#define DRV_MODULE_RELDATE "March 28, 2007" +#define DRV_MODULE_VERSION "1.5.7" +#define DRV_MODULE_RELDATE "March 29, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -3099,20 +3099,18 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if ((align_start = (offset32 & 3))) { offset32 &= ~3; - len32 += (4 - align_start); + len32 += align_start; + if (len32 < 4) + len32 = 4; if ((rc = bnx2_nvram_read(bp, offset32, start, 4))) return rc; } if (len32 & 3) { - if ((len32 > 4) || !align_start) { - align_end = 4 - (len32 & 3); - len32 += align_end; - if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, - end, 4))) { - return rc; - } - } + align_end = 4 - (len32 & 3); + len32 += align_end; + if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4))) + return rc; } if (align_start || align_end) { @@ -3187,17 +3185,17 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if ((rc = bnx2_enable_nvram_write(bp)) != 0) goto nvram_write_end; - /* Erase the page */ - if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) - goto nvram_write_end; - - /* Re-enable the write again for the actual write */ - bnx2_enable_nvram_write(bp); - /* Loop to write back the buffer data from page_start to * data_start */ i = 0; if (bp->flash_info->buffered == 0) { + /* Erase the page */ + if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) + goto nvram_write_end; + + /* Re-enable the write again for the actual write */ + bnx2_enable_nvram_write(bp); + for (addr = page_start; addr < data_start; addr += 4, i += 4) { -- cgit v1.2.2 From 9f238486f5438b2e44f760b11fa3a08714c1ddb6 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 31 Mar 2007 00:23:13 -0700 Subject: cxgb3 - Safeguard TCAM size usage Ensure that the TCAM active region size is at least 16. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/common.h | 3 +++ drivers/net/cxgb3/cxgb3_main.c | 7 +++++-- drivers/net/cxgb3/cxgb3_offload.c | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 85e5543cfb57..38a0565ad1c1 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -358,6 +358,9 @@ enum { MC5_MODE_72_BIT = 2 }; +/* MC5 min active region size */ +enum { MC5_MIN_TIDS = 16 }; + struct vpd_params { unsigned int cclk; unsigned int mclk; diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d55383610559..b82544e08689 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -485,12 +485,14 @@ static ssize_t show_##name(struct device *d, struct device_attribute *attr, \ static ssize_t set_nfilters(struct net_device *dev, unsigned int val) { struct adapter *adap = dev->priv; + int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0; if (adap->flags & FULL_INIT_DONE) return -EBUSY; if (val && adap->params.rev == 0) return -EINVAL; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers) + if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers - + min_tids) return -EINVAL; adap->params.mc5.nfilters = val; return 0; @@ -508,7 +510,8 @@ static ssize_t set_nservers(struct net_device *dev, unsigned int val) if (adap->flags & FULL_INIT_DONE) return -EBUSY; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters) + if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters - + MC5_MIN_TIDS) return -EINVAL; adap->params.mc5.nservers = val; return 0; diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index f6ed033efb56..eed7a48e3111 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -553,7 +553,9 @@ int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client, struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; spin_lock_bh(&t->atid_lock); - if (t->afree) { + if (t->afree && + t->atids_in_use + atomic_read(&t->tids_in_use) + MC5_MIN_TIDS <= + t->ntids) { union active_open_entry *p = t->afree; atid = (p - t->atid_tab) + t->atid_base; -- cgit v1.2.2 From 8ac3ba68e25a73594646ec30b7c482b364644c92 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 31 Mar 2007 00:23:19 -0700 Subject: cxgb3 - detect NIC only adapters Differentiate NIC only adapters from RNICs. Initialize offload capabilities for RNICs only. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/common.h | 6 +++--- drivers/net/cxgb3/cxgb3_main.c | 8 ++++---- drivers/net/cxgb3/mc5.c | 3 +++ drivers/net/cxgb3/sge.c | 2 +- drivers/net/cxgb3/t3_hw.c | 24 ++++++++++++++++++------ 5 files changed, 29 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 38a0565ad1c1..97128d88eaef 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -112,8 +112,7 @@ enum { }; enum { - SUPPORTED_OFFLOAD = 1 << 24, - SUPPORTED_IRQ = 1 << 25 + SUPPORTED_IRQ = 1 << 24 }; enum { /* adapter interrupt-maintained statistics */ @@ -405,6 +404,7 @@ struct adapter_params { unsigned int stats_update_period; /* MAC stats accumulation period */ unsigned int linkpoll_period; /* link poll period in 0.1s */ unsigned int rev; /* chip revision */ + unsigned int offload; }; enum { /* chip revisions */ @@ -605,7 +605,7 @@ static inline int is_10G(const struct adapter *adap) static inline int is_offload(const struct adapter *adap) { - return adapter_info(adap)->caps & SUPPORTED_OFFLOAD; + return adap->params.offload; } static inline unsigned int core_ticks_per_usec(const struct adapter *adap) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index b82544e08689..145b67cc1d2e 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -407,7 +407,7 @@ static void quiesce_rx(struct adapter *adap) static int setup_sge_qsets(struct adapter *adap) { int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0; - unsigned int ntxq = is_offload(adap) ? SGE_TXQ_PER_SET : 1; + unsigned int ntxq = SGE_TXQ_PER_SET; if (adap->params.rev > 0 && !(adap->flags & USING_MSI)) irq_idx = -1; @@ -922,7 +922,7 @@ static int cxgb_open(struct net_device *dev) return err; set_bit(pi->port_id, &adapter->open_device_map); - if (!ofld_disable) { + if (is_offload(adapter) && !ofld_disable) { err = offload_open(dev); if (err) printk(KERN_WARNING @@ -2270,9 +2270,9 @@ static void __devinit print_port_info(struct adapter *adap, if (!test_bit(i, &adap->registered_device_map)) continue; - printk(KERN_INFO "%s: %s %s RNIC (rev %d) %s%s\n", + printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n", dev->name, ai->desc, pi->port_type->desc, - adap->params.rev, buf, + is_offload(adap) ? "R" : "", adap->params.rev, buf, (adap->flags & USING_MSIX) ? " MSI-X" : (adap->flags & USING_MSI) ? " MSI" : ""); if (adap->name == dev->name && adap->params.vpd.mclk) diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c index 644d62ea86a6..84c1ffa8e2d3 100644 --- a/drivers/net/cxgb3/mc5.c +++ b/drivers/net/cxgb3/mc5.c @@ -328,6 +328,9 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, unsigned int tcam_size = mc5->tcam_size; struct adapter *adap = mc5->adapter; + if (!tcam_size) + return 0; + if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size) return -EINVAL; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index c23783432e51..027ab2c3825c 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2631,7 +2631,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->txq[TXQ_ETH].stop_thres = nports * flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); - if (ntxq == 1) { + if (!is_offload(adapter)) { #ifdef USE_RX_PAGE q->fl[0].buf_size = RX_PAGE_SIZE; #else diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 791ed6dc1943..d83f075ef2d7 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -438,23 +438,23 @@ static const struct adapter_info t3_adap_info[] = { {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, + 0, &mi1_mdio_ops, "Chelsio PE9000"}, {2, 0, 0, 0, F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, + 0, &mi1_mdio_ops, "Chelsio T302"}, {1, 0, 0, 0, F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, + SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T310"}, {2, 0, 0, 0, F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, + SUPPORTED_10000baseT_Full | SUPPORTED_AUI, &mi1_mdio_ext_ops, "Chelsio T320"}, }; @@ -2900,6 +2900,9 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type) struct adapter *adapter = mc7->adapter; const struct mc7_timing_params *p = &mc7_timings[mem_type]; + if (!mc7->size) + return 0; + val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); slow = val & F_SLOW; width = G_WIDTH(val); @@ -3100,8 +3103,10 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) do { /* wait for uP to initialize */ msleep(20); } while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts); - if (!attempts) + if (!attempts) { + CH_ERR(adapter, "uP initialization timed out\n"); goto out_err; + } err = 0; out_err: @@ -3201,7 +3206,7 @@ static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7, mc7->name = name; mc7->offset = base_addr - MC7_PMRX_BASE_ADDR; cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); - mc7->size = mc7_calc_size(cfg); + mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg); mc7->width = G_WIDTH(cfg); } @@ -3228,6 +3233,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1)); t3_write_reg(adapter, A_T3DBG_GPIO_EN, ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL); + t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0); if (adapter->params.rev == 0 || !uses_xaui(adapter)) val |= F_ENRGMII; @@ -3326,7 +3332,13 @@ int __devinit t3_prep_adapter(struct adapter *adapter, p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size); p->ntimer_qs = p->cm_size >= (128 << 20) || adapter->params.rev > 0 ? 12 : 6; + } + + adapter->params.offload = t3_mc7_size(&adapter->pmrx) && + t3_mc7_size(&adapter->pmtx) && + t3_mc7_size(&adapter->cm); + if (is_offload(adapter)) { adapter->params.mc5.nservers = DEFAULT_NSERVERS; adapter->params.mc5.nfilters = adapter->params.rev > 0 ? DEFAULT_NFILTERS : 0; -- cgit v1.2.2 From 6d6dabac382604db22ff51c5e0d25af18529ac8b Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 31 Mar 2007 00:23:24 -0700 Subject: cxgb3 - Tighten xgmac workaround Run the watchdog task when the link is up. Flush the XGMAC Tx FIFO when the link drops. Also remove a statistics update that should have gone in the previous modification of xgmac.c. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 16 +++++++++++++--- drivers/net/cxgb3/regs.h | 4 ++++ drivers/net/cxgb3/xgmac.c | 1 - 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 145b67cc1d2e..512daf738948 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -185,16 +185,26 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, int speed, int duplex, int pause) { struct net_device *dev = adapter->port[port_id]; + struct port_info *pi = netdev_priv(dev); + struct cmac *mac = &pi->mac; /* Skip changes from disabled ports. */ if (!netif_running(dev)) return; if (link_stat != netif_carrier_ok(dev)) { - if (link_stat) + if (link_stat) { + t3_set_reg_field(adapter, + A_XGM_TXFIFO_CFG + mac->offset, + F_ENDROPPKT, 0); netif_carrier_on(dev); - else + } else { netif_carrier_off(dev); + t3_set_reg_field(adapter, + A_XGM_TXFIFO_CFG + mac->offset, + F_ENDROPPKT, F_ENDROPPKT); + } + link_report(dev); } } @@ -2119,7 +2129,7 @@ static void check_t3b2_mac(struct adapter *adapter) continue; status = 0; - if (netif_running(dev)) + if (netif_running(dev) && netif_carrier_ok(dev)) status = t3b2_mac_watchdog_task(&p->mac); if (status == 1) p->mac.stats.num_toggled++; diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index b38629a244d0..f8be41c5a081 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1940,6 +1940,10 @@ #define V_TXFIFOTHRESH(x) ((x) << S_TXFIFOTHRESH) +#define S_ENDROPPKT 21 +#define V_ENDROPPKT(x) ((x) << S_ENDROPPKT) +#define F_ENDROPPKT V_ENDROPPKT(1U) + #define A_XGM_SERDES_CTRL 0x890 #define A_XGM_SERDES_CTRL0 0x8e0 diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 2b42c13ba8e0..94aaff005a35 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -471,7 +471,6 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac) RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); - mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); if (mac->adapter->params.rev == T3_REV_B2) -- cgit v1.2.2 From 7f672cf5b2382310d530469f1f78f69bf48adedc Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 31 Mar 2007 00:23:30 -0700 Subject: cxgb3 - Firwmare update Introduce FW micro version. Bump up FW version to 3.3.0 Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 4 ++-- drivers/net/cxgb3/version.h | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 512daf738948..26240fd5e768 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -721,7 +721,7 @@ static void bind_qsets(struct adapter *adap) } } -#define FW_FNAME "t3fw-%d.%d.bin" +#define FW_FNAME "t3fw-%d.%d.%d.bin" static int upgrade_fw(struct adapter *adap) { @@ -731,7 +731,7 @@ static int upgrade_fw(struct adapter *adap) struct device *dev = &adap->pdev->dev; snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, - FW_VERSION_MINOR); + FW_VERSION_MINOR, FW_VERSION_MICRO); ret = request_firmware(&fw, buf, dev); if (ret < 0) { dev_err(dev, "could not upgrade firmware: unable to load %s\n", diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index 82278f850259..042e27e291cd 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -36,6 +36,9 @@ #define DRV_NAME "cxgb3" /* Driver version */ #define DRV_VERSION "1.0-ko" + +/* Firmware version */ #define FW_VERSION_MAJOR 3 -#define FW_VERSION_MINOR 2 +#define FW_VERSION_MINOR 3 +#define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ -- cgit v1.2.2 From cda22aa94d3fe3942476b3652b8b92c653b96ee3 Mon Sep 17 00:00:00 2001 From: Bill Helfinstine Date: Sun, 1 Apr 2007 13:10:28 -0400 Subject: b44: fix IFF_ALLMULTI handling of CAM slots If you set the IFF_ALLMULTI flag on a b44 device, or if you join more than B44_MCAST_TABLE_SIZE multicast groups, the device will stop receiving unicast messages. This is because the __b44_set_mac_addr call sets the zeroth CAM entry to the MAC address of the device, and then the loop at line 1722 proceeds to overwrite it unless the value of i is set by the __b44_load_mcast call. However, when IFF_ALLMULTI is set, that call is bypassed, leaving i set to zero. Fixed by starting the loop at 1 to make it skip the CAM entry for the MAC address. Signed-off-by: Bill Helfinstine Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index aaada572732a..d742bfe24471 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1709,7 +1709,7 @@ static void __b44_set_rx_mode(struct net_device *dev) bw32(bp, B44_RXCONFIG, val); } else { unsigned char zero[6] = {0, 0, 0, 0, 0, 0}; - int i = 0; + int i = 1; __b44_set_mac_addr(bp); -- cgit v1.2.2 From 99f252b097a3bd6280047ba2175b605671da4a23 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 2 Apr 2007 22:59:59 +0200 Subject: r8169: issue request_irq after the private data are completely initialized The irq handler schedules a NAPI poll request unconditionally as soon as the status register is not clean. It has been there - and wrong - for ages but a recent timing change made it apparently easier to trigger. Signed-off-by: Francois Romieu Cc: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/r8169.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 521b5f0618a4..60f630e84bf0 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -66,6 +66,7 @@ VERSION 2.2LK <2005/01/25> #include #include +#include #include #include @@ -486,6 +487,7 @@ static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, void __iomem *); static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); static void rtl8169_down(struct net_device *dev); +static void rtl8169_rx_clear(struct rtl8169_private *tp); #ifdef CONFIG_R8169_NAPI static int rtl8169_poll(struct net_device *dev, int *budget); @@ -1751,16 +1753,10 @@ static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; - int retval; + int retval = -ENOMEM; - rtl8169_set_rxbufsize(tp, dev); - - retval = - request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, dev->name, dev); - if (retval < 0) - goto out; - retval = -ENOMEM; + rtl8169_set_rxbufsize(tp, dev); /* * Rx and Tx desscriptors needs 256 bytes alignment. @@ -1769,19 +1765,26 @@ static int rtl8169_open(struct net_device *dev) tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, &tp->TxPhyAddr); if (!tp->TxDescArray) - goto err_free_irq; + goto out; tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, &tp->RxPhyAddr); if (!tp->RxDescArray) - goto err_free_tx; + goto err_free_tx_0; retval = rtl8169_init_ring(dev); if (retval < 0) - goto err_free_rx; + goto err_free_rx_1; INIT_DELAYED_WORK(&tp->task, NULL); + smp_mb(); + + retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, + dev->name, dev); + if (retval < 0) + goto err_release_ring_2; + rtl8169_hw_start(dev); rtl8169_request_timer(dev); @@ -1790,14 +1793,14 @@ static int rtl8169_open(struct net_device *dev) out: return retval; -err_free_rx: +err_release_ring_2: + rtl8169_rx_clear(tp); +err_free_rx_1: pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, tp->RxPhyAddr); -err_free_tx: +err_free_tx_0: pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, tp->TxPhyAddr); -err_free_irq: - free_irq(dev->irq, dev); goto out; } -- cgit v1.2.2 From 1371fa6db0bbb8e23f988a641f5ae7361bc629dd Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 2 Apr 2007 23:01:11 +0200 Subject: r8169: fix suspend/resume for down interface The PM hooks are no-op if the r8169 interface is down (i.e. !IFF_UP). However, as the chipset is enabled, the device will not work after a suspend/resume cycle. The patch always issue the required PCI suspend sequence and removes the module unload/reload workaround. Signed-off-by: Arnaud Patard Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/r8169.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 60f630e84bf0..6a77b8a92245 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2890,7 +2890,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) void __iomem *ioaddr = tp->mmio_addr; if (!netif_running(dev)) - goto out; + goto out_pci_suspend; netif_device_detach(dev); netif_stop_queue(dev); @@ -2904,10 +2904,11 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) spin_unlock_irq(&tp->lock); +out_pci_suspend: pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); pci_set_power_state(pdev, pci_choose_state(pdev, state)); -out: + return 0; } @@ -2915,15 +2916,15 @@ static int rtl8169_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + if (!netif_running(dev)) goto out; netif_device_attach(dev); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - rtl8169_schedule_work(dev, rtl8169_reset_task); out: return 0; -- cgit v1.2.2 From b8fa2f3a82069304acac1f9e957d491585f4f49a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 6 Apr 2007 17:35:37 -0700 Subject: [TG3]: Fix crash during tg3_init_one(). The driver will crash when the chip has been initialized by EFI before tg3_init_one(). In this case, the driver will call tg3_chip_reset() before allocating consistent memory. The bug is fixed by checking for tp->hw_status before accessing it during tg3_chip_reset(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0acee9f324e9..256969e1300c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4834,8 +4834,10 @@ static int tg3_chip_reset(struct tg3 *tp) * sharing or irqpoll. */ tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING; - tp->hw_status->status = 0; - tp->hw_status->status_tag = 0; + if (tp->hw_status) { + tp->hw_status->status = 0; + tp->hw_status->status_tag = 0; + } tp->last_tag = 0; smp_mb(); synchronize_irq(tp->pdev->irq); -- cgit v1.2.2 From 699784b7614ce61b16a075445b8e5b6c379c5086 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 9 Apr 2007 11:51:15 -0700 Subject: [SC92031]: Fix priv->lock context The spin_lock calls made in dev->open and dev->close must disable BH since open/close are made in process context. Conversely, the call in dev->hard_start_xmit does not need to disable BH since it is already executing with BH disabled. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/sc92031.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 4a926f20b6ea..c32c21af3fdd 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -964,7 +964,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } - spin_lock_bh(&priv->lock); + spin_lock(&priv->lock); if (unlikely(!netif_carrier_ok(dev))) { err = -ENOLINK; @@ -1005,7 +1005,7 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); out_unlock: - spin_unlock_bh(&priv->lock); + spin_unlock(&priv->lock); out: dev_kfree_skb(skb); @@ -1042,12 +1042,12 @@ static int sc92031_open(struct net_device *dev) priv->pm_config = 0; /* Interrupts already disabled by sc92031_stop or sc92031_probe */ - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_reset(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); sc92031_enable_interrupts(dev); if (netif_carrier_ok(dev)) @@ -1077,13 +1077,13 @@ static int sc92031_stop(struct net_device *dev) /* Disable interrupts, stop Tx and Rx. */ sc92031_disable_interrupts(dev); - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_disable_tx_rx(dev); _sc92031_tx_clear(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); free_irq(pdev->irq, dev); pci_free_consistent(pdev, TX_BUF_TOT_LEN, priv->tx_bufs, @@ -1539,13 +1539,13 @@ static int sc92031_suspend(struct pci_dev *pdev, pm_message_t state) /* Disable interrupts, stop Tx and Rx. */ sc92031_disable_interrupts(dev); - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_disable_tx_rx(dev); _sc92031_tx_clear(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); out: pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1565,12 +1565,12 @@ static int sc92031_resume(struct pci_dev *pdev) goto out; /* Interrupts already disabled by sc92031_suspend */ - spin_lock(&priv->lock); + spin_lock_bh(&priv->lock); _sc92031_reset(dev); mmiowb(); - spin_unlock(&priv->lock); + spin_unlock_bh(&priv->lock); sc92031_enable_interrupts(dev); netif_device_attach(dev); -- cgit v1.2.2 From ae6ead4623bfbc57f3945ff86f27e51811e2e91b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sun, 11 Mar 2007 19:54:11 +0000 Subject: [PATCH] zd1211rw: Reject AL2230S devices zd1211rw currently detects AL2230S-based devices as AL2230, and hence programs the RF incorrectly. Transmit silently fails on this misconfiguration. After this patch, AL2230S devices are rejected with an error message, to avoid any confusion with an apparent driver bug. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 1 + drivers/net/wireless/zd1211rw/zd_chip.h | 2 +- drivers/net/wireless/zd1211rw/zd_rf_al2230.c | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 9c64f894b71b..9d299bd18850 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -337,6 +337,7 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) chip->patch_cr157 = (value >> 13) & 0x1; chip->patch_6m_band_edge = (value >> 21) & 0x1; chip->new_phy_layout = (value >> 31) & 0x1; + chip->al2230s_bit = (value >> 7) & 0x1; chip->link_led = ((value >> 4) & 1) ? LED1 : LED2; chip->supports_tx_led = 1; if (value & (1 << 24)) { /* LED scenario */ diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index b07569e391ee..ae39c225bc9e 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -711,7 +711,7 @@ struct zd_chip { u16 link_led; unsigned int pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, - new_phy_layout:1, + new_phy_layout:1, al2230s_bit:1, is_zd1211b:1, supports_tx_led:1; }; diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 25323a13a3db..5235a7827ac5 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -358,6 +358,12 @@ int zd_rf_init_al2230(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); + if (chip->al2230s_bit) { + dev_err(zd_chip_dev(chip), "AL2230S devices are not yet " + "supported by this driver.\n"); + return -ENODEV; + } + rf->switch_radio_off = al2230_switch_radio_off; if (chip->is_zd1211b) { rf->init_hw = zd1211b_al2230_init_hw; -- cgit v1.2.2 From 92b3e2e9253a9f4c9224071842fd263c334dece0 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 3 Apr 2007 23:17:37 +0100 Subject: [PATCH] zd1211rw: Fix E2P_PHY_REG patching Due to conflicting/confusing defines in the vendor driver, we were reading E2P_PHY_REG from the wrong location. CR157 patching was slightly incorrect in that the vendor driver only patches in an 8-bit value, whereas we were patching 24 bits. Additionally, CR157 patching was happening on both zd1211 and zd1211b, but this should only happen on zd1211. Signed-off-by: Daniel Drake Signed-off-by: Ulrich Kunitz Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 11 +++-------- drivers/net/wireless/zd1211rw/zd_chip.h | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 9d299bd18850..87ee3ee020fe 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -592,16 +592,16 @@ int zd_chip_unlock_phy_regs(struct zd_chip *chip) return r; } -/* CR157 can be optionally patched by the EEPROM */ +/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ static int patch_cr157(struct zd_chip *chip) { int r; - u32 value; + u16 value; if (!chip->patch_cr157) return 0; - r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); + r = zd_ioread16_locked(chip, &value, E2P_PHY_REG); if (r) return r; @@ -791,11 +791,6 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip) goto out; r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - goto unlock; - - r = patch_cr157(chip); -unlock: t = zd_chip_unlock_phy_regs(chip); if (t && !r) r = t; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index ae39c225bc9e..e57ed75d9425 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -641,8 +641,8 @@ enum { * also only 11 channels. */ #define E2P_ALLOWED_CHANNEL E2P_DATA(0x18) -#define E2P_PHY_REG E2P_DATA(0x1a) #define E2P_DEVICE_VER E2P_DATA(0x20) +#define E2P_PHY_REG E2P_DATA(0x25) #define E2P_36M_CAL_VALUE1 E2P_DATA(0x28) #define E2P_36M_CAL_VALUE2 E2P_DATA(0x2a) #define E2P_36M_CAL_VALUE3 E2P_DATA(0x2c) -- cgit v1.2.2 From 81e880064dd32b3efdc41ad4cc2416c4744693ee Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 7 Apr 2007 13:54:35 -0500 Subject: [PATCH] bcm43xx: Fix 802.11b/g scan limits to match regulatory reqs In 802.11b/g mode, bcm43xx actively scans channels 1-14 no matter what locale has been set, either in the sprom or by the locale option. This behaviorviolates regulatory rules everywhere in the world except Japan. This patch changes the default range to the correct value if the locale has been set, and to channels 1-13 if no locale has been set. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 80cb88eb98c6..a38e7eec0e62 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -946,6 +946,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; + u8 max_bg_channel; geo = kzalloc(sizeof(*geo), GFP_KERNEL); if (!geo) @@ -967,6 +968,23 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) } iso_country = bcm43xx_locale_iso(bcm->sprom.locale); +/* set the maximum channel based on locale set in sprom or witle locale option */ + switch (bcm->sprom.locale) { + case BCM43xx_LOCALE_THAILAND: + case BCM43xx_LOCALE_ISRAEL: + case BCM43xx_LOCALE_JORDAN: + case BCM43xx_LOCALE_USA_CANADA_ANZ: + case BCM43xx_LOCALE_USA_LOW: + max_bg_channel = 11; + break; + case BCM43xx_LOCALE_JAPAN: + case BCM43xx_LOCALE_JAPAN_HIGH: + max_bg_channel = 14; + break; + default: + max_bg_channel = 13; + } + if (have_a) { for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) { @@ -978,7 +996,7 @@ static int bcm43xx_geo_init(struct bcm43xx_private *bcm) } if (have_bg) { for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; - channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) { + channel <= max_bg_channel; channel++) { chan = &geo->bg[i++]; chan->freq = bcm43xx_channel_to_freq_bg(channel); chan->channel = channel; -- cgit v1.2.2 From ec759a2b383b50950be37fbe470c4cc2ca18e2ce Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 7 Apr 2007 14:11:03 -0500 Subject: [PATCH] bcm43xx: Fix PPC machine checks and match loopback gain specs The specifications for loopback_gain calculation and for G PHY initialization have been updated. This patch implements them and fixes a machine check error that occurs for PPC architecture with a phy->rev of 1. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 57 +++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index d1e89be965cd..72529a440f15 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -978,7 +978,7 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup_phy[15]; + u16 backup_phy[15] = {0}; u16 backup_radio[3]; u16 backup_bband; u16 i; @@ -989,8 +989,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); - backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); - backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + if (phy->rev != 1) { + backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); + backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + } backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); @@ -1018,14 +1020,16 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) bcm43xx_phy_read(bcm, 0x0811) | 0x0001); bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0002); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0002); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + } bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x000C); bcm43xx_phy_write(bcm, 0x0812, @@ -1048,10 +1052,12 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) bcm43xx_phy_read(bcm, 0x000A) | 0x2000); } - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + } bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); @@ -1138,8 +1144,10 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) } } - bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); - bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); + bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + } bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); @@ -1188,24 +1196,23 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0811, 0x0000); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); } - if (phy->rev >= 3) { + if (phy->rev > 5) { bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); } if (phy->rev >= 2 && phy->connected) { tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp < 6) { + if (tmp ==3 || tmp == 5) { bcm43xx_phy_write(bcm, 0x04C2, 0x1816); bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - if (tmp != 3) { + if (tmp == 5) { bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) & 0x00FF) | 0x1F00); } } - } - if (phy->rev < 3 && phy->connected) bcm43xx_phy_write(bcm, 0x047E, 0x0078); + } if (radio->revision == 8) { bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); @@ -1232,7 +1239,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) if (phy->rev >= 6) { bcm43xx_phy_write(bcm, 0x0036, (bcm43xx_phy_read(bcm, 0x0036) - & 0xF000) | (radio->txctl2 << 12)); + & 0x0FFF) | (radio->txctl2 << 12)); } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) bcm43xx_phy_write(bcm, 0x002E, 0x8075); @@ -1243,7 +1250,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) else bcm43xx_phy_write(bcm, 0x002F, 0x0202); } - if (phy->connected) { + if (phy->connected || phy->rev >= 2) { bcm43xx_phy_lo_adjust(bcm, 0); bcm43xx_phy_write(bcm, 0x080F, 0x8078); } @@ -1257,7 +1264,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) */ bcm43xx_nrssi_hw_update(bcm, 0xFFFF); bcm43xx_calc_nrssi_threshold(bcm); - } else if (phy->connected) { + } else if (phy->connected || phy->rev >= 2) { if (radio->nrssi[0] == -1000) { assert(radio->nrssi[1] == -1000); bcm43xx_calc_nrssi_slope(bcm); -- cgit v1.2.2 From e5b9ddd9a0f95e133db7b43d05978f24cd6f1369 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 7 Apr 2007 16:02:25 -0700 Subject: skge: turn carrier off when down Driver needs to turn off carrier when down, otherwise it can confuse bonding and bridging and looks like carrier is on immediately when it is brought back up. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 39c6677dff5e..cc907a1a5ecc 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2535,6 +2535,7 @@ static int skge_down(struct net_device *dev) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); netif_stop_queue(dev); + netif_carrier_off(dev); if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) del_timer_sync(&skge->link_timer); -- cgit v1.2.2 From 9a87240c67565578a9533101b930ef4a975be333 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 7 Apr 2007 16:02:26 -0700 Subject: sky2: turn carrier off when down Driver needs to turn off carrier when down. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ab0ab92583fe..45c4525a46e4 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1561,6 +1561,7 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); + netif_carrier_off(dev); /* Disable port IRQ */ imask = sky2_read32(hw, B0_IMSK); -- cgit v1.2.2 From 1ad5b4a5c224c5f98f9745adbcf99899624c8138 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 7 Apr 2007 16:02:27 -0700 Subject: sky2: turn on clocks when doing resume Some of these chips are disabled until clock is enabled. This fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=404107 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 45c4525a46e4..b636b8a55ffb 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3770,6 +3770,11 @@ static int sky2_resume(struct pci_dev *pdev) goto out; pci_enable_wake(pdev, PCI_D0, 0); + + /* Re-enable all clocks */ + if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); -- cgit v1.2.2 From 9467a8fc89844ff2ea9c6d13460dddb3b674cc37 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 7 Apr 2007 16:02:28 -0700 Subject: sky2: phy workarounds for Yukon EC-U A1 The workaround Yukon EC-U wasn't comparing with correct version and wasn't doing correct setup. Without it, 88e8056 throws all sorts of errors. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b636b8a55ffb..4a009b7b1777 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -510,9 +510,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ledover &= ~PHY_M_LED_MO_RX; } - if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + hw->chip_rev == CHIP_REV_YU_EC_U_A1) { /* apply fixes in PHY AFE */ - pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); /* increase differential signal amplitude in 10BASE-T */ @@ -524,7 +524,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, 0x17, 0x2002); /* set page register to 0 */ - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); } else if (hw->chip_id != CHIP_ID_YUKON_EX) { gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); -- cgit v1.2.2 From 692412b31ffb5df00197ea591dd635fc07506c02 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 9 Apr 2007 15:32:45 -0700 Subject: skge: fix wake on lan Need to rework wake on lan code to setup properly and get activated on shutdown (and suspend), not when ethtool is run. This does not need to go to stable queue because wake on lan was not even included in 2.6.20 (or earlier versions). Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 94 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index cc907a1a5ecc..d476a3cc2e94 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -163,27 +163,46 @@ static void skge_wol_init(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - enum pause_control save_mode; - u32 ctrl; + u16 ctrl; - /* Bring hardware out of reset */ skge_write16(hw, B0_CTST, CS_RST_CLR); skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + /* Turn on Vaux */ + skge_write8(hw, B0_POWER_CTRL, + PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - /* Force to 10/100 skge_reset will re-enable on resume */ - save_mode = skge->flow_control; - skge->flow_control = FLOW_MODE_SYMMETRIC; + /* WA code for COMA mode -- clear PHY reset */ + if (hw->chip_id == CHIP_ID_YUKON_LITE && + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { + u32 reg = skge_read32(hw, B2_GP_IO); + reg |= GP_DIR_9; + reg &= ~GP_IO_9; + skge_write32(hw, B2_GP_IO, reg); + } - ctrl = skge->advertising; - skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); + skge_write32(hw, SK_REG(port, GPHY_CTRL), + GPC_DIS_SLEEP | + GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | + GPC_ANEG_1 | GPC_RST_SET); - skge_phy_reset(skge); + skge_write32(hw, SK_REG(port, GPHY_CTRL), + GPC_DIS_SLEEP | + GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | + GPC_ANEG_1 | GPC_RST_CLR); + + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); + + /* Force to 10/100 skge_reset will re-enable on resume */ + gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, + PHY_AN_100FULL | PHY_AN_100HALF | + PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA); + /* no 1000 HD/FD */ + gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_CTRL, + PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE | + PHY_CT_RE_CFG | PHY_CT_DUP_MD); - skge->flow_control = save_mode; - skge->advertising = ctrl; /* Set GMAC to no flow control and auto update for speed/duplex */ gma_write16(hw, port, GM_GP_CTRL, @@ -227,12 +246,10 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; - if (wol->wolopts & wol_supported(hw)) + if (wol->wolopts & ~wol_supported(hw)) return -EOPNOTSUPP; skge->wol = wol->wolopts; - if (!netif_running(dev)) - skge_wol_init(skge); return 0; } @@ -2535,11 +2552,12 @@ static int skge_down(struct net_device *dev) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); netif_stop_queue(dev); - netif_carrier_off(dev); + if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) del_timer_sync(&skge->link_timer); netif_poll_disable(dev); + netif_carrier_off(dev); spin_lock_irq(&hw->hw_lock); hw->intr_mask &= ~portmask[port]; @@ -3766,21 +3784,6 @@ static void __devexit skge_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int vaux_avail(struct pci_dev *pdev) -{ - int pm_cap; - - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 ctl; - pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl); - if (ctl & PCI_PM_CAP_AUX_POWER) - return 1; - } - return 0; -} - - static int skge_suspend(struct pci_dev *pdev, pm_message_t state) { struct skge_hw *hw = pci_get_drvdata(pdev); @@ -3802,10 +3805,6 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) wol |= skge->wol; } - if (wol && vaux_avail(pdev)) - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - skge_write32(hw, B0_IMSK, 0); pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -3851,6 +3850,28 @@ out: } #endif +static void skge_shutdown(struct pci_dev *pdev) +{ + struct skge_hw *hw = pci_get_drvdata(pdev); + int i, wol = 0; + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct skge_port *skge = netdev_priv(dev); + + if (skge->wol) + skge_wol_init(skge); + wol |= skge->wol; + } + + pci_enable_wake(pdev, PCI_D3hot, wol); + pci_enable_wake(pdev, PCI_D3cold, wol); + + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + +} + static struct pci_driver skge_driver = { .name = DRV_NAME, .id_table = skge_id_table, @@ -3860,6 +3881,7 @@ static struct pci_driver skge_driver = { .suspend = skge_suspend, .resume = skge_resume, #endif + .shutdown = skge_shutdown, }; static int __init skge_init_module(void) -- cgit v1.2.2 From f2d961c9827bab4b64a1b4ea30c68cf5ab2b2330 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 9 Apr 2007 20:10:22 -0700 Subject: cxgb3 - avoid deadlock with mac watchdog Fix a deadlock when the interface s configured down and the watchdog tack is sleeping on rtnl_lock. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 26240fd5e768..c6ebe25464ca 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2119,7 +2119,9 @@ static void check_t3b2_mac(struct adapter *adapter) { int i; - rtnl_lock(); /* synchronize with ifdown */ + if (!rtnl_trylock()) /* synchronize with ifdown */ + return; + for_each_port(adapter, i) { struct net_device *dev = adapter->port[i]; struct port_info *p = netdev_priv(dev); -- cgit v1.2.2 From 59cf81076a85e1df273155298c462574b49cc0fe Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 9 Apr 2007 20:10:27 -0700 Subject: cxgb3 - MAC watchdog update The MAC watchdog was failing if the peer interface was brought down. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/common.h | 7 ++- drivers/net/cxgb3/cxgb3_main.c | 10 ++-- drivers/net/cxgb3/xgmac.c | 107 ++++++++++++++++++++++++++++++----------- 3 files changed, 89 insertions(+), 35 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 97128d88eaef..8d1379633698 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -478,8 +478,11 @@ struct cmac { struct adapter *adapter; unsigned int offset; unsigned int nucast; /* # of address filters for unicast MACs */ - unsigned int tcnt; - unsigned int xcnt; + unsigned int tx_tcnt; + unsigned int tx_xcnt; + u64 tx_mcnt; + unsigned int rx_xcnt; + u64 rx_mcnt; unsigned int toggle_cnt; unsigned int txen; struct mac_stats stats; diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index c6ebe25464ca..d6eb9824a10c 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -194,15 +194,13 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, if (link_stat != netif_carrier_ok(dev)) { if (link_stat) { - t3_set_reg_field(adapter, - A_XGM_TXFIFO_CFG + mac->offset, - F_ENDROPPKT, 0); + t3_mac_enable(mac, MAC_DIRECTION_RX); netif_carrier_on(dev); } else { netif_carrier_off(dev); - t3_set_reg_field(adapter, - A_XGM_TXFIFO_CFG + mac->offset, - F_ENDROPPKT, F_ENDROPPKT); + pi->phy.ops->power_down(&pi->phy, 1); + t3_mac_disable(mac, MAC_DIRECTION_RX); + t3_link_start(&pi->phy, mac, &pi->link_config); } link_report(dev); diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 94aaff005a35..a506792f9575 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -367,7 +367,8 @@ int t3_mac_enable(struct cmac *mac, int which) int idx = macidx(mac); struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; - + struct mac_stats *s = &mac->stats; + if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); @@ -376,10 +377,16 @@ int t3_mac_enable(struct cmac *mac, int which) t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); - mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, - A_TP_PIO_DATA))); - mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, - A_XGM_TX_SPI4_SOP_EOP_CNT))); + mac->tx_mcnt = s->tx_frames; + mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, + A_TP_PIO_DATA))); + mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT + + oft))); + mac->rx_mcnt = s->rx_frames; + mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_RX_SPI4_SOP_EOP_CNT + + oft))); mac->txen = F_TXEN; mac->toggle_cnt = 0; } @@ -392,6 +399,7 @@ int t3_mac_disable(struct cmac *mac, int which) { int idx = macidx(mac); struct adapter *adap = mac->adapter; + int val; if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); @@ -401,44 +409,89 @@ int t3_mac_disable(struct cmac *mac, int which) t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); mac->txen = 0; } - if (which & MAC_DIRECTION_RX) + if (which & MAC_DIRECTION_RX) { + t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, + F_PCS_RESET_, 0); + msleep(100); t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); + val = F_MAC_RESET_; + if (is_10G(adap)) + val |= F_PCS_RESET_; + else if (uses_xaui(adap)) + val |= F_PCS_RESET_ | F_XG2G_RESET_; + else + val |= F_RGMII_RESET_ | F_XG2G_RESET_; + t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val); + } return 0; } int t3b2_mac_watchdog_task(struct cmac *mac) { struct adapter *adap = mac->adapter; - unsigned int tcnt, xcnt; + struct mac_stats *s = &mac->stats; + unsigned int tx_tcnt, tx_xcnt; + unsigned int tx_mcnt = s->tx_frames; + unsigned int rx_mcnt = s->rx_frames; + unsigned int rx_xcnt; int status; - t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac)); - tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); - xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, - A_XGM_TX_SPI4_SOP_EOP_CNT + - mac->offset))); - - if (tcnt != mac->tcnt && xcnt == 0 && mac->xcnt == 0) { - if (mac->toggle_cnt > 4) { - t3b2_mac_reset(mac); + if (tx_mcnt == mac->tx_mcnt) { + tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_TX_SPI4_SOP_EOP_CNT + + mac->offset))); + if (tx_xcnt == 0) { + t3_write_reg(adap, A_TP_PIO_ADDR, + A_TP_TX_DROP_CNT_CH0 + macidx(mac)); + tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, + A_TP_PIO_DATA))); + } else { mac->toggle_cnt = 0; + return 0; + } + } else { + mac->toggle_cnt = 0; + return 0; + } + + if (((tx_tcnt != mac->tx_tcnt) && + (tx_xcnt == 0) && (mac->tx_xcnt == 0)) || + ((mac->tx_mcnt == tx_mcnt) && + (tx_xcnt != 0) && (mac->tx_xcnt != 0))) { + if (mac->toggle_cnt > 4) status = 2; - } else { - t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); - t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); - t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, - mac->txen); - t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); - mac->toggle_cnt++; + else status = 1; - } } else { mac->toggle_cnt = 0; - status = 0; + return 0; } - mac->tcnt = tcnt; - mac->xcnt = xcnt; + if (rx_mcnt != mac->rx_mcnt) + rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, + A_XGM_RX_SPI4_SOP_EOP_CNT + + mac->offset))); + else + return 0; + + if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0) + status = 2; + + mac->tx_tcnt = tx_tcnt; + mac->tx_xcnt = tx_xcnt; + mac->tx_mcnt = s->tx_frames; + mac->rx_xcnt = rx_xcnt; + mac->rx_mcnt = s->rx_frames; + if (status == 1) { + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ + t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen); + t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ + mac->toggle_cnt++; + } else if (status == 2) { + t3b2_mac_reset(mac); + mac->toggle_cnt = 0; + } return status; } -- cgit v1.2.2 From 6cdbd77e8883aac2e24f8b19b91e5b1c839213a0 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 9 Apr 2007 20:10:33 -0700 Subject: cxgb3 - missing CPL hanler and register setting. Remove specific CPL handler. Add missing CPL handler. Add missing register setting when the interface is brought up. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 2 ++ drivers/net/cxgb3/cxgb3_offload.c | 14 ++------------ drivers/net/cxgb3/regs.h | 6 ++++++ 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d6eb9824a10c..67b4b219d927 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -770,6 +770,8 @@ static int cxgb_up(struct adapter *adap) if (err) goto out; + t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12)); + err = setup_sge_qsets(adap); if (err) goto out; diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index eed7a48e3111..48649244673e 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -743,17 +743,6 @@ static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb) } } -static int do_set_tcb_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_set_tcb_rpl *rpl = cplhdr(skb); - - if (rpl->status != CPL_ERR_NONE) - printk(KERN_ERR - "Unexpected SET_TCB_RPL status %u for tid %u\n", - rpl->status, GET_TID(rpl)); - return CPL_RET_BUF_DONE; -} - static int do_trace(struct t3cdev *dev, struct sk_buff *skb) { struct cpl_trace_pkt *p = cplhdr(skb); @@ -1215,7 +1204,8 @@ void __init cxgb3_offload_init(void) t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl); t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss); t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish); - t3_register_cpl_handler(CPL_SET_TCB_RPL, do_set_tcb_rpl); + t3_register_cpl_handler(CPL_SET_TCB_RPL, do_hwtid_rpl); + t3_register_cpl_handler(CPL_GET_TCB_RPL, do_hwtid_rpl); t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term); t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl); t3_register_cpl_handler(CPL_TRACE_PKT, do_trace); diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index f8be41c5a081..e5a553410e24 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1234,9 +1234,15 @@ #define A_ULPRX_ISCSI_TAGMASK 0x514 +#define S_HPZ0 0 +#define M_HPZ0 0xf +#define V_HPZ0(x) ((x) << S_HPZ0) +#define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0) + #define A_ULPRX_TDDP_LLIMIT 0x51c #define A_ULPRX_TDDP_ULIMIT 0x520 +#define A_ULPRX_TDDP_PSZ 0x528 #define A_ULPRX_STAG_LLIMIT 0x52c -- cgit v1.2.2 From ae8509b1876e6e1074edc9846296e80983e30502 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 10 Apr 2007 21:21:08 +0200 Subject: myri10ge: fix management of the firmware 4KB boundary crossing restriction Simpler way of dealing with the firmware 4KB boundary crossing restriction for rx buffers. This fixes a variety of memory corruption issues when using an "uncommon" MTU with a 16KB page size. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c216e6a5d235..1e7fa2facbe1 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -900,19 +900,9 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, /* try to refill entire ring */ while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) { idx = rx->fill_cnt & rx->mask; - - if ((bytes < MYRI10GE_ALLOC_SIZE / 2) && - (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) { + if (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE) { /* we can use part of previous page */ get_page(rx->page); -#if MYRI10GE_ALLOC_SIZE > 4096 - /* Firmware cannot cross 4K boundary.. */ - if ((rx->page_offset >> 12) != - ((rx->page_offset + bytes - 1) >> 12)) { - rx->page_offset = - (rx->page_offset + bytes) & ~4095; - } -#endif } else { /* we need a new page */ page = @@ -941,6 +931,13 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, /* start next packet on a cacheline boundary */ rx->page_offset += SKB_DATA_ALIGN(bytes); + +#if MYRI10GE_ALLOC_SIZE > 4096 + /* don't cross a 4KB boundary */ + if ((rx->page_offset >> 12) != + ((rx->page_offset + bytes - 1) >> 12)) + rx->page_offset = (rx->page_offset + 4096) & ~4095; +#endif rx->fill_cnt++; /* copy 8 descriptors to the firmware at a time */ -- cgit v1.2.2 From f19baaeaadf9d77bcc6c122500c70b27c5bbc7a4 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 10 Apr 2007 21:21:39 +0200 Subject: myri10ge: more Intel chipsets providing aligned PCIe completions Add the Intel 5000 southbridge (aka Intel 6310/6311/6321ESB) PCIe ports and the Intel E30x0 chipsets to the whitelist of aligned PCIe completion. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1e7fa2facbe1..756855930f34 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2487,6 +2487,10 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) #define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 #define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa +#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 0x3510 +#define PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4 0x351b +#define PCI_DEVICE_ID_INTEL_E3000_PCIE 0x2779 +#define PCI_DEVICE_ID_INTEL_E3010_PCIE 0x277a #define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST 0x140 #define PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST 0x142 @@ -2526,6 +2530,18 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_FIRST && bridge->device <= PCI_DEVICE_ID_SERVERWORKS_HT2100_PCIE_LAST) + /* All Intel E3000/E3010 PCIE ports */ + || (bridge->vendor == PCI_VENDOR_ID_INTEL + && (bridge->device == + PCI_DEVICE_ID_INTEL_E3000_PCIE + || bridge->device == + PCI_DEVICE_ID_INTEL_E3010_PCIE)) + /* All Intel 6310/6311/6321ESB PCIE ports */ + || (bridge->vendor == PCI_VENDOR_ID_INTEL + && bridge->device >= + PCI_DEVICE_ID_INTEL_6300ESB_PCIEE1 + && bridge->device <= + PCI_DEVICE_ID_INTEL_6300ESB_PCIEE4) /* All Intel E5000 PCIE ports */ || (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device >= -- cgit v1.2.2 From 4b2281c7aa6a6e2615b35f8cebd93656dc6d714c Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 10 Apr 2007 21:22:19 +0200 Subject: myri10ge: update driver version to 1.3.0-1.233 Update the myri10ge driver version number to 1.3.0-1.233. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 756855930f34..f8efe0e70a6b 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -71,7 +71,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.0-1.227" +#define MYRI10GE_VERSION_STR "1.3.0-1.233" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); -- cgit v1.2.2 From 606fcd0b94f7531f52a9b07008a4461213cbcd27 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Tue, 17 Apr 2007 11:06:30 -0700 Subject: cxgb3 - Fix low memory conditions Reuse the incoming skb when a clientless abort req is recieved. The release of RDMA connections HW resources might be deferred in low memory situations. Ensure that no further activity is passed up to the RDMA driver for these connections. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_defs.h | 5 ++- drivers/net/cxgb3/cxgb3_offload.c | 69 +++++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h index e14862b43d17..483a594210a7 100644 --- a/drivers/net/cxgb3/cxgb3_defs.h +++ b/drivers/net/cxgb3/cxgb3_defs.h @@ -67,7 +67,10 @@ static inline union listen_entry *stid2entry(const struct tid_info *t, static inline struct t3c_tid_entry *lookup_tid(const struct tid_info *t, unsigned int tid) { - return tid < t->ntids ? &(t->tid_tab[tid]) : NULL; + struct t3c_tid_entry *t3c_tid = tid < t->ntids ? + &(t->tid_tab[tid]) : NULL; + + return (t3c_tid && t3c_tid->client) ? t3c_tid : NULL; } /* diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index 48649244673e..199e5066acf3 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -508,6 +508,7 @@ void cxgb3_queue_tid_release(struct t3cdev *tdev, unsigned int tid) spin_lock_bh(&td->tid_release_lock); p->ctx = (void *)td->tid_release_list; + p->client = NULL; td->tid_release_list = p; if (!p->ctx) schedule_work(&td->tid_release_task); @@ -623,7 +624,8 @@ static int do_act_open_rpl(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid); - if (t3c_tid->ctx && t3c_tid->client && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client && + t3c_tid->client->handlers && t3c_tid->client->handlers[CPL_ACT_OPEN_RPL]) { return t3c_tid->client->handlers[CPL_ACT_OPEN_RPL] (dev, skb, t3c_tid-> @@ -642,7 +644,7 @@ static int do_stid_rpl(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_stid(&(T3C_DATA(dev))->tid_maps, stid); - if (t3c_tid->ctx && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers && t3c_tid->client->handlers[p->opcode]) { return t3c_tid->client->handlers[p->opcode] (dev, skb, t3c_tid->ctx); @@ -660,7 +662,7 @@ static int do_hwtid_rpl(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers && t3c_tid->client->handlers[p->opcode]) { return t3c_tid->client->handlers[p->opcode] (dev, skb, t3c_tid->ctx); @@ -689,6 +691,28 @@ static int do_cr(struct t3cdev *dev, struct sk_buff *skb) } } +/* + * Returns an sk_buff for a reply CPL message of size len. If the input + * sk_buff has no other users it is trimmed and reused, otherwise a new buffer + * is allocated. The input skb must be of size at least len. Note that this + * operation does not destroy the original skb data even if it decides to reuse + * the buffer. + */ +static struct sk_buff *cxgb3_get_cpl_reply_skb(struct sk_buff *skb, size_t len, + int gfp) +{ + if (likely(!skb_cloned(skb))) { + BUG_ON(skb->len < len); + __skb_trim(skb, len); + skb_get(skb); + } else { + skb = alloc_skb(len, gfp); + if (skb) + __skb_put(skb, len); + } + return skb; +} + static int do_abort_req_rss(struct t3cdev *dev, struct sk_buff *skb) { union opcode_tid *p = cplhdr(skb); @@ -696,30 +720,39 @@ static int do_abort_req_rss(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers && t3c_tid->client->handlers[p->opcode]) { return t3c_tid->client->handlers[p->opcode] (dev, skb, t3c_tid->ctx); } else { struct cpl_abort_req_rss *req = cplhdr(skb); struct cpl_abort_rpl *rpl; + struct sk_buff *reply_skb; + unsigned int tid = GET_TID(req); + u8 cmd = req->status; + + if (req->status == CPL_ERR_RTX_NEG_ADVICE || + req->status == CPL_ERR_PERSIST_NEG_ADVICE) + goto out; - struct sk_buff *skb = - alloc_skb(sizeof(struct cpl_abort_rpl), GFP_ATOMIC); - if (!skb) { + reply_skb = cxgb3_get_cpl_reply_skb(skb, + sizeof(struct + cpl_abort_rpl), + GFP_ATOMIC); + + if (!reply_skb) { printk("do_abort_req_rss: couldn't get skb!\n"); goto out; } - skb->priority = CPL_PRIORITY_DATA; - __skb_put(skb, sizeof(struct cpl_abort_rpl)); - rpl = cplhdr(skb); + reply_skb->priority = CPL_PRIORITY_DATA; + __skb_put(reply_skb, sizeof(struct cpl_abort_rpl)); + rpl = cplhdr(reply_skb); rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL)); - rpl->wr.wr_lo = htonl(V_WR_TID(GET_TID(req))); - OPCODE_TID(rpl) = - htonl(MK_OPCODE_TID(CPL_ABORT_RPL, GET_TID(req))); - rpl->cmd = req->status; - cxgb3_ofld_send(dev, skb); + rpl->wr.wr_lo = htonl(V_WR_TID(tid)); + OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, tid)); + rpl->cmd = cmd; + cxgb3_ofld_send(dev, reply_skb); out: return CPL_RET_BUF_DONE; } @@ -732,7 +765,7 @@ static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid); - if (t3c_tid->ctx && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers && t3c_tid->client->handlers[CPL_ACT_ESTABLISH]) { return t3c_tid->client->handlers[CPL_ACT_ESTABLISH] (dev, skb, t3c_tid->ctx); @@ -762,7 +795,7 @@ static int do_term(struct t3cdev *dev, struct sk_buff *skb) struct t3c_tid_entry *t3c_tid; t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && + if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers && t3c_tid->client->handlers[opcode]) { return t3c_tid->client->handlers[opcode] (dev, skb, t3c_tid->ctx); @@ -961,7 +994,7 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) for (tid = 0; tid < ti->ntids; tid++) { te = lookup_tid(ti, tid); BUG_ON(!te); - if (te->ctx && te->client && te->client->redirect) { + if (te && te->ctx && te->client && te->client->redirect) { update_tcb = te->client->redirect(te->ctx, old, new, e); if (update_tcb) { l2t_hold(L2DATA(tdev), e); -- cgit v1.2.2 From 1ca03cbc2057f61390e8e8a3234dc0bb0a8fe57a Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Tue, 17 Apr 2007 11:06:36 -0700 Subject: cxgb3 - PHY interrupts and GPIO pins. Remove assumption that PHY interrupts use GPIOs 3 and 5. Deal with PHY interrupts connected to any GPIO pins. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/t3_hw.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index d83f075ef2d7..fb485d0a43d8 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1523,19 +1523,25 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx) */ int t3_phy_intr_handler(struct adapter *adapter) { - static const int intr_gpio_bits[] = { 8, 0x20 }; - + u32 mask, gpi = adapter_info(adapter)->gpio_intr; u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); for_each_port(adapter, i) { - if (cause & intr_gpio_bits[i]) { - struct cphy *phy = &adap2pinfo(adapter, i)->phy; - int phy_cause = phy->ops->intr_handler(phy); + struct port_info *p = adap2pinfo(adapter, i); + + mask = gpi - (gpi & (gpi - 1)); + gpi -= mask; + + if (!(p->port_type->caps & SUPPORTED_IRQ)) + continue; + + if (cause & mask) { + int phy_cause = p->phy.ops->intr_handler(&p->phy); if (phy_cause & cphy_cause_link_change) t3_link_changed(adapter, i); if (phy_cause & cphy_cause_fifo_error) - phy->fifo_errors++; + p->phy.fifo_errors++; } } -- cgit v1.2.2 From 33bdeec80649f2eab36039f63d69c65378493cbe Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 16 Apr 2007 22:54:13 -0700 Subject: spidernet: Fix problem sending IP fragments The basic structure of "normal" UDP/IP/Ethernet frames (that actually work): - It starts with the Ethernet header (dest MAC, src MAC, etc.) - The next part is occupied by the IP header (version info, length of packet, id=0, fragment offset=0, checksum, from / to address, etc.) - Then comes the UDP header (src / dest port, length, checksum) - Actual payload - Ethernet checksum Now what's different for IP fragment: - The IP header has id set to some value (same for all fragments), offset is set appropriately (i.e. 0 for first fragment, following according to size of other fragments), size is the length of the frame. - UDP header is unchanged. I.e. length is according to full UDP datagram, not just the part within the actual frame! But this is only true within the first frame: all following frames don't have a valid UDP-header at all. The spidernet silicon seems to be quite intelligent: It's able to compute (IP / UDP / Ethernet) checksums on the fly and tests if frames are conforming to RFC -- at least conforming to RFC on complete frames. But IP fragments are different as explained above: I.e. for IP fragments containing part of a UDP datagram it sees incompatible length in the headers for IP and UDP in the first frame and, thus, skips this frame. But the content *is* correct for IP fragments. For all following frames it finds (most probably) no valid UDP header at all. But this *is* also correct for IP fragments. The Linux IP-stack seems to be clever in this point. It expects the spidernet to calculate the checksum (since the module claims to be able to do so) and marks the skb's for "normal" frames accordingly (ip_summed set to CHECKSUM_HW). But for the IP fragments it does not expect the driver to be capable to handle the frames appropriately. Thus all checksums are allready computed. This is also flaged within the skb (ip_summed set to CHECKSUM_NONE). Unfortunately the spidernet driver ignores that hints. It tries to send the IP fragments of UDP datagrams as normal UDP/IP frames. Since they have different structure the silicon detects them the be not "well-formed" and skips them. The following one-liner against 2.6.21-rc2 changes this behavior. If the IP-stack claims to have done the checksumming, the driver should not try to checksum (and analyze) the frame but send it as is. Signed-off-by: Norbert Eicker Signed-off-by: Linas Vepstas Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 3b91af89e4c7..e3019d52c30f 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -719,7 +719,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS; spin_unlock_irqrestore(&chain->lock, flags); - if (skb->protocol == htons(ETH_P_IP)) + if (skb->protocol == htons(ETH_P_IP) && skb->ip_summed == CHECKSUM_PARTIAL) switch (skb->nh.iph->protocol) { case IPPROTO_TCP: hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP; -- cgit v1.2.2 From bf41a7c5d94a3d197002bdf11892529b47a63e99 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Thu, 12 Apr 2007 10:57:06 -0700 Subject: gianfar needs crc32 lib dependency Gianfar needs crc32 to be selected to compile. Signed-off-by: Dave Jiang -- drivers/net/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) -- Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c3f9f599f134..a3d46ea37126 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2263,6 +2263,7 @@ config GIANFAR tristate "Gianfar Ethernet" depends on 85xx || 83xx || PPC_86xx select PHYLIB + select CRC32 help This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, and MPC86xx family of chips, and the FEC on the 8540. -- cgit v1.2.2 From 0a17e4c252ce951615f3c1fccae6d6262c8d4187 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:47:58 -0700 Subject: sky2: disable support for 88E8056 This device is having all sorts of problems that lead to data corruption and system instability. It gets receive status and data out of order, it generates descriptor and TSO errors, etc. Until the problems are resolved, it should not be used by anyone who cares about there system. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4a009b7b1777..98b1f3acff86 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -123,7 +123,10 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ +#ifdef broken + /* This device causes data corruption problems that are not resolved */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ +#endif { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ -- cgit v1.2.2 From 40b01727a5a65597160f1738d3fbe63de902f0cb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:47:59 -0700 Subject: sky2: handle descriptor errors There should never be descriptor error unless hardware or driver is buggy. But if an error occurs, print useful information, clear irq, and recover. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 67 +++++++++++++++++++++++++++++------------------------- drivers/net/sky2.h | 3 +++ 2 files changed, 39 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 98b1f3acff86..a2cc721a2bf5 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2343,26 +2343,22 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) } } -/* This should never happen it is a fatal situation */ -static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, - const char *rxtx, u32 mask) +/* This should never happen it is a bug. */ +static void sky2_le_error(struct sky2_hw *hw, unsigned port, + u16 q, unsigned ring_size) { struct net_device *dev = hw->dev[port]; struct sky2_port *sky2 = netdev_priv(dev); - u32 imask; - - printk(KERN_ERR PFX "%s: %s descriptor error (hardware problem)\n", - dev ? dev->name : "", rxtx); + unsigned idx; + const u64 *le = (q == Q_R1 || q == Q_R2) + ? (u64 *) sky2->rx_le : (u64 *) sky2->tx_le; - imask = sky2_read32(hw, B0_IMSK); - imask &= ~mask; - sky2_write32(hw, B0_IMSK, imask); + idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); + printk(KERN_ERR PFX "%s: descriptor error q=%#x get=%u [%llx] put=%u\n", + dev->name, (unsigned) q, idx, (unsigned long long) le[idx], + (unsigned) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX))); - if (dev) { - spin_lock(&sky2->phy_lock); - sky2_link_down(sky2); - spin_unlock(&sky2->phy_lock); - } + sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); } /* If idle then force a fake soft NAPI poll once a second @@ -2386,23 +2382,15 @@ static void sky2_idle(unsigned long arg) mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); } - -static int sky2_poll(struct net_device *dev0, int *budget) +/* Hardware/software error handling */ +static void sky2_err_intr(struct sky2_hw *hw, u32 status) { - struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; - int work_limit = min(dev0->quota, *budget); - int work_done = 0; - u32 status = sky2_read32(hw, B0_Y2_SP_EISR); + if (net_ratelimit()) + dev_warn(&hw->pdev->dev, "error interrupt status=%#x\n", status); if (status & Y2_IS_HW_ERR) sky2_hw_intr(hw); - if (status & Y2_IS_IRQ_PHY1) - sky2_phy_intr(hw, 0); - - if (status & Y2_IS_IRQ_PHY2) - sky2_phy_intr(hw, 1); - if (status & Y2_IS_IRQ_MAC1) sky2_mac_intr(hw, 0); @@ -2410,16 +2398,33 @@ static int sky2_poll(struct net_device *dev0, int *budget) sky2_mac_intr(hw, 1); if (status & Y2_IS_CHK_RX1) - sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); + sky2_le_error(hw, 0, Q_R1, RX_LE_SIZE); if (status & Y2_IS_CHK_RX2) - sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); + sky2_le_error(hw, 1, Q_R2, RX_LE_SIZE); if (status & Y2_IS_CHK_TXA1) - sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); + sky2_le_error(hw, 0, Q_XA1, TX_RING_SIZE); if (status & Y2_IS_CHK_TXA2) - sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); + sky2_le_error(hw, 1, Q_XA2, TX_RING_SIZE); +} + +static int sky2_poll(struct net_device *dev0, int *budget) +{ + struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; + int work_limit = min(dev0->quota, *budget); + int work_done = 0; + u32 status = sky2_read32(hw, B0_Y2_SP_EISR); + + if (unlikely(status & Y2_IS_ERROR)) + sky2_err_intr(hw, status); + + if (status & Y2_IS_IRQ_PHY1) + sky2_phy_intr(hw, 0); + + if (status & Y2_IS_IRQ_PHY2) + sky2_phy_intr(hw, 1); work_done = sky2_status_intr(hw, work_limit); if (work_done < work_limit) { diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index ac24bdc42976..9ca4a2c061c6 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -288,6 +288,9 @@ enum { | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1, Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2, + Y2_IS_ERROR = Y2_IS_HW_ERR | + Y2_IS_IRQ_MAC1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_RX1 | + Y2_IS_IRQ_MAC2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_RX2, }; /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -- cgit v1.2.2 From 4f44d8ba09280a7f0887ab60277940d6c72f2b43 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:48:00 -0700 Subject: sky2: disable ASF on all chip types Need to make sure and disable ASF on all chip types. Otherwise, there may be random reboots. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a2cc721a2bf5..910c600a6caf 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2542,16 +2542,14 @@ static void sky2_reset(struct sky2_hw *hw) int i; /* disable ASF */ - if (hw->chip_id <= CHIP_ID_YUKON_EC) { - if (hw->chip_id == CHIP_ID_YUKON_EX) { - status = sky2_read16(hw, HCU_CCSR); - status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | - HCU_CCSR_UC_STATE_MSK); - sky2_write16(hw, HCU_CCSR, status); - } else - sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); - sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); - } + if (hw->chip_id == CHIP_ID_YUKON_EX) { + status = sky2_read16(hw, HCU_CCSR); + status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | + HCU_CCSR_UC_STATE_MSK); + sky2_write16(hw, HCU_CCSR, status); + } else + sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); + sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); /* do a SW reset */ sky2_write8(hw, B0_CTST, CS_RST_SET); -- cgit v1.2.2 From b628ed986d681c708aec64418c2c7f6a6b715855 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:48:01 -0700 Subject: sky2: EC-U performance and jumbo support The Yukon EC Ultra chips have transmit settings for store and forward and PCI buffering. By setting these appropriately, normal performance goes from 750Mbytes/sec to 940Mbytes/sec (non-jumbo). It is also possible to do Jumbo mode, but it means turning off TSO and checksum offload so the performance gets worse. There isn't enough buffering for checksum offload to work. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 85 ++++++++++++++++++++++++++++++++++++++---------------- drivers/net/sky2.h | 8 +++++ 2 files changed, 68 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 910c600a6caf..4d1ec78c437a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -743,12 +743,17 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); - if (hw->dev[port]->mtu > ETH_DATA_LEN) { - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 0x180); - /* Disable Store & Forward mode for TX */ - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); - } + + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); + + if (hw->dev[port]->mtu > ETH_DATA_LEN) + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); + else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); } } @@ -1281,7 +1286,7 @@ static int sky2_up(struct net_device *dev) /* Set almost empty threshold */ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_U_A0) - sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0); + sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV); sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, TX_RING_SIZE - 1); @@ -1587,13 +1592,6 @@ static int sky2_down(struct net_device *dev) sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET | RB_DIS_OP_MD); - /* WA for dev. #4.209 */ - if (hw->chip_id == CHIP_ID_YUKON_EC_U - && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - sky2->speed != SPEED_1000 ? - TX_STFW_ENA : TX_STFW_DIS); - ctrl = gma_read16(hw, port, GM_GP_CTRL); ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); gma_write16(hw, port, GM_GP_CTRL, ctrl); @@ -1893,6 +1891,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; int err; u16 ctl, mode; u32 imask; @@ -1900,10 +1899,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; - /* TSO on Yukon Ultra and MTU > 1500 not supported */ - if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN) - dev->features &= ~NETIF_F_TSO; - if (!netif_running(dev)) { dev->mtu = new_mtu; return 0; @@ -1918,8 +1913,18 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) synchronize_irq(hw->pdev->irq); - ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); - gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { + if (new_mtu > ETH_DATA_LEN) { + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); + dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); + } + + ctl = gma_read16(hw, port, GM_GP_CTRL); + gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); sky2_rx_stop(sky2); sky2_rx_clean(sky2); @@ -1931,9 +1936,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (dev->mtu > ETH_DATA_LEN) mode |= GM_SMOD_JUMBO_ENA; - gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode); + gma_write16(hw, port, GM_SERIAL_MODE, mode); - sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); + sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); err = sky2_rx_start(sky2); sky2_write32(hw, B0_IMSK, imask); @@ -1941,7 +1946,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (err) dev_close(dev); else { - gma_write16(hw, sky2->port, GM_GP_CTRL, ctl); + gma_write16(hw, port, GM_GP_CTRL, ctl); netif_poll_enable(hw->dev[0]); netif_wake_queue(dev); @@ -3334,6 +3339,36 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs->len - B3_RI_WTO_R1); } +/* In order to do Jumbo packets on these chips, need to turn off the + * transmit store/forward. Therefore checksum offload won't work. + */ +static int no_tx_offload(struct net_device *dev) +{ + const struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; + + return dev->mtu > ETH_DATA_LEN && + (hw->chip_id == CHIP_ID_YUKON_EX + || hw->chip_id == CHIP_ID_YUKON_EC_U); +} + +static int sky2_set_tx_csum(struct net_device *dev, u32 data) +{ + if (data && no_tx_offload(dev)) + return -EINVAL; + + return ethtool_op_set_tx_csum(dev, data); +} + + +static int sky2_set_tso(struct net_device *dev, u32 data) +{ + if (data && no_tx_offload(dev)) + return -EINVAL; + + return ethtool_op_set_tso(dev, data); +} + static const struct ethtool_ops sky2_ethtool_ops = { .get_settings = sky2_get_settings, .set_settings = sky2_set_settings, @@ -3349,9 +3384,9 @@ static const struct ethtool_ops sky2_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, + .set_tx_csum = sky2_set_tx_csum, .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, + .set_tso = sky2_set_tso, .get_rx_csum = sky2_get_rx_csum, .set_rx_csum = sky2_set_rx_csum, .get_strings = sky2_get_strings, diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 9ca4a2c061c6..5efb5afc45ba 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -741,6 +741,11 @@ enum { TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ + + /* Threshold values for Yukon-EC Ultra and Extreme */ + ECU_AE_THR = 0x0070, /* Almost Empty Threshold */ + ECU_TXFF_LEV = 0x01a0, /* Tx BMU FIFO Level */ + ECU_JUMBO_WM = 0x0080, /* Jumbo Mode Watermark */ }; /* Descriptor Poll Timer Registers */ @@ -1634,6 +1639,9 @@ enum { TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */ TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */ + TX_JUMBO_ENA = 1<<23,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */ + TX_JUMBO_DIS = 1<<22,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */ + GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */ -- cgit v1.2.2 From d2adf4f65a70f94cbb3bb4dffd4bbc70cc383071 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:48:02 -0700 Subject: sky2: no jumbo on Yukon FE The Yukon FE (100mbit only) chips do not support large packets. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4d1ec78c437a..6950b2d685e1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1899,6 +1899,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; + if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) + return -EINVAL; + if (!netif_running(dev)) { dev->mtu = new_mtu; return 0; -- cgit v1.2.2 From 93cd791e02bbdb504aba024a14fdc07fe246bc71 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 11 Apr 2007 14:48:03 -0700 Subject: sky2: version 1.14 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6950b2d685e1..ac36152c68bf 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -49,7 +49,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.13" +#define DRV_VERSION "1.14" #define PFX DRV_NAME " " /* -- cgit v1.2.2 From 7c5050e3e49f6d89af0d63111611693d9625d1f5 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 19 Apr 2007 13:05:52 -0700 Subject: [PPP]: Fix skbuff.c:BUG due incorrect logic in process_input_packet() From: Paul Mackerras This fixes: Subject: kernel BUG at net/core/skbuff.c in linux-2.6.21-rc6 process_input_packet() treats the case where the first byte is 0xff (PPP_ALLSTATIONS) but the second byte is 0x03 (PPP_UI) as indicating a packet with a PPP protocol number of 0xff. Arguably that's wrong since PPP protocol 0xff is reserved, and the RFC does envision the possibility of receiving frames where the control field has values other than 0x03. Signed-off-by: David S. Miller --- drivers/net/ppp_async.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 933e2f3c77aa..caabbc408c34 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -802,9 +802,9 @@ process_input_packet(struct asyncppp *ap) /* check for address/control and protocol compression */ p = skb->data; - if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { + if (p[0] == PPP_ALLSTATIONS) { /* chop off address/control */ - if (skb->len < 3) + if (p[1] != PPP_UI || skb->len < 3) goto err; p = skb_pull(skb, 2); } -- cgit v1.2.2 From 46fcc86dd71d70211e965102fb69414c90381880 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 19 Apr 2007 18:21:01 -0700 Subject: Revert "e1000: fix NAPI performance on 4-port adapters" This reverts commit 60cba200f11b6f90f35634c5cd608773ae3721b7. It's been linked to lockups of the e1000 hardware, see for example https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=229603 but it's likely that the commit itself is not really introducing the bug, but just allowing an unrelated problem to rear its ugly head (ie one current working theory is that the code exposes us to a hardware race condition by decreasing the amount of time we spend in each NAPI poll cycle). We'll revert it until root cause is known. Intel has a repeatable reproduction on two different machines and bus traces of the hardware doing something bad. Acked-by: Jesse Brandeburg Cc: Jeff Garzik Cc: David S. Miller Cc: Greg KH Cc: Dave Jones Cc: Auke Kok Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/e1000/e1000_main.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 1d08e937af82..b28a915bd980 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3796,7 +3796,7 @@ e1000_intr_msi(int irq, void *data) for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & - e1000_clean_tx_irq(adapter, adapter->tx_ring))) + !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; if (likely(adapter->itr_setting & 3)) @@ -3899,7 +3899,7 @@ e1000_intr(int irq, void *data) for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & - e1000_clean_tx_irq(adapter, adapter->tx_ring))) + !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; if (likely(adapter->itr_setting & 3)) @@ -3949,7 +3949,7 @@ e1000_clean(struct net_device *poll_dev, int *budget) poll_dev->quota -= work_done; /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((tx_cleaned && (work_done < work_to_do)) || + if ((!tx_cleaned && (work_done == 0)) || !netif_running(poll_dev)) { quit_polling: if (likely(adapter->itr_setting & 3)) @@ -3979,7 +3979,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, #ifdef CONFIG_E1000_NAPI unsigned int count = 0; #endif - boolean_t cleaned = TRUE; + boolean_t cleaned = FALSE; unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; @@ -4013,10 +4013,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, #ifdef CONFIG_E1000_NAPI #define E1000_TX_WEIGHT 64 /* weight of a sort for tx, to avoid endless transmit cleanup */ - if (count++ == E1000_TX_WEIGHT) { - cleaned = FALSE; - break; - } + if (count++ == E1000_TX_WEIGHT) break; #endif } -- cgit v1.2.2 From d0dc1129c2e5a5a0e53940cad44333e6bd2f9af3 Mon Sep 17 00:00:00 2001 From: Marcel van Nies Date: Sat, 21 Apr 2007 15:31:58 -0700 Subject: [SUNQE]: Fix MAC address assignment. The MAC address assignment at module loading is simply forgotten. The bug at module unloading is caused by an incorrect call. The bug at module unloading does not only happen for sunqe, sunlance and sunhme (sbus) suffer from it too. I've tested this on my SS20. Signed-off-by: Marcel van Nies Signed-off-by: David S. Miller --- drivers/net/sunqe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 7874eb1ef043..f3bad56d476a 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -845,6 +845,8 @@ static int __init qec_ether_init(struct sbus_dev *sdev) if (!dev) return -ENOMEM; + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + qe = netdev_priv(dev); i = of_getintprop_default(sdev->ofdev.node, "channel#", -1); @@ -960,7 +962,7 @@ static int __devexit qec_sbus_remove(struct of_device *dev) struct sunqe *qp = dev_get_drvdata(&dev->dev); struct net_device *net_dev = qp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); sbus_iounmap(qp->qcregs, CREG_REG_SIZE); sbus_iounmap(qp->mregs, MREGS_REG_SIZE); -- cgit v1.2.2 From 9f9b6693ed8254177bafcb823b0ea3659d61adb0 Mon Sep 17 00:00:00 2001 From: Marcel van Nies Date: Sat, 21 Apr 2007 15:34:10 -0700 Subject: [SUNLANCE]: Fix module unload. Signed-off-by: Marcel van Nies Signed-off-by: David S. Miller --- drivers/net/sunlance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 5b00d79b5573..b0929a457b60 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1550,7 +1550,7 @@ static int __exit sunlance_sun4_remove(void) struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); struct net_device *net_dev = lp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); lance_free_hwresources(lp); @@ -1590,7 +1590,7 @@ static int __devexit sunlance_sbus_remove(struct of_device *dev) struct lance_private *lp = dev_get_drvdata(&dev->dev); struct net_device *net_dev = lp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); lance_free_hwresources(lp); -- cgit v1.2.2 From c3b99f0db9b2ef4292ef774bae1ea0d6f1e8d82a Mon Sep 17 00:00:00 2001 From: Marcel van Nies Date: Sat, 21 Apr 2007 15:34:55 -0700 Subject: [SUNHME]: Fix module unload. Signed-off-by: Marcel van Nies Signed-off-by: David S. Miller --- drivers/net/sunhme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index ef671739cfea..192bbc91c731 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -3314,7 +3314,7 @@ static int __devexit hme_sbus_remove(struct of_device *dev) struct happy_meal *hp = dev_get_drvdata(&dev->dev); struct net_device *net_dev = hp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); /* XXX qfe parent interrupt... */ -- cgit v1.2.2 From c445a31cd7f469d77acc37538ab43a99530968b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=2E=C3=87a=C4=9Flar=20Onur?= Date: Sun, 22 Apr 2007 00:52:48 +0300 Subject: Add missing USRobotics Wireless Adapter (Model 5423) id into zd1211rw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USRobotics Wireless Adapter (Model 5423) works well with current zd1211rw driver also (i have tested 2.6.18, 2.6.20 and 2.6.21-rc7). It just needs its ID added to the list of devices. Signed-off-by: S.Çağlar Onur Signed-off-by: Linus Torvalds --- 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 aac8a1c5ba08..edaaad2f648b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -62,6 +62,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, {} -- cgit v1.2.2 From d91c088b39e3c66d309938de858775bb90fd1ead Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Tue, 24 Apr 2007 12:40:57 -0400 Subject: [netdrvr] depca: handle platform_device_add() failure The following patch fixes a kernel bug in depca_platform_probe(). We don't use a dynamic pointer for pldev->dev.platform_data, so it seems that the correct way to proceed if platform_device_add(pldev) fails is to explicitly set the pldev->dev.platform_data pointer to NULL, before calling the platform_device_put(pldev), or it will be kfree'ed by platform_device_release(). Signed-off-by: Jeff Garzik --- drivers/net/depca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 5113eef755b9..f3807aaf10aa 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1491,8 +1491,9 @@ static void __init depca_platform_probe (void) depca_io_ports[i].device = pldev; if (platform_device_add(pldev)) { - platform_device_put(pldev); depca_io_ports[i].device = NULL; + pldev->dev.platform_data = NULL; + platform_device_put(pldev); continue; } -- cgit v1.2.2 From b748d9e3b80dc7e6ce6bf7399f57964b99a4104c Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 20 Apr 2007 09:54:58 -0400 Subject: sis900: Allocate rx replacement buffer before rx operation The sis900 driver appears to have a bug in which the receive routine passes the skbuff holding the received frame to the network stack before refilling the buffer in the rx ring. If a new skbuff cannot be allocated, the driver simply leaves a hole in the rx ring, which causes the driver to stop receiving frames and become non-recoverable without an rmmod/insmod according to reporters. This patch reverses that order, attempting to allocate a replacement buffer first, and receiving the new frame only if one can be allocated. If no skbuff can be allocated, the current skbuf in the rx ring is recycled, dropping the current frame, but keeping the NIC operational. Signed-off-by: Neil Horman Signed-off-by: Jeff Garzik --- drivers/net/sis900.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index b3750f284279..b2a3b19d773a 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1755,6 +1755,24 @@ static int sis900_rx(struct net_device *net_dev) } else { struct sk_buff * skb; + pci_unmap_single(sis_priv->pci_dev, + sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, + PCI_DMA_FROMDEVICE); + + /* refill the Rx buffer, what if there is not enought + * memory for new socket buffer ?? */ + if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { + /* + * Not enough memory to refill the buffer + * so we need to recycle the old one so + * as to avoid creating a memory hole + * in the rx ring + */ + skb = sis_priv->rx_skbuff[entry]; + sis_priv->stats.rx_dropped++; + goto refill_rx_ring; + } + /* This situation should never happen, but due to some unknow bugs, it is possible that we are working on NULL sk_buff :-( */ @@ -1768,9 +1786,6 @@ static int sis900_rx(struct net_device *net_dev) break; } - pci_unmap_single(sis_priv->pci_dev, - sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); /* give the socket buffer to upper layers */ skb = sis_priv->rx_skbuff[entry]; skb_put(skb, rx_size); @@ -1783,33 +1798,14 @@ static int sis900_rx(struct net_device *net_dev) net_dev->last_rx = jiffies; sis_priv->stats.rx_bytes += rx_size; sis_priv->stats.rx_packets++; - - /* refill the Rx buffer, what if there is not enought - * memory for new socket buffer ?? */ - if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { - /* not enough memory for skbuff, this makes a - * "hole" on the buffer ring, it is not clear - * how the hardware will react to this kind - * of degenerated buffer */ - if (netif_msg_rx_status(sis_priv)) - printk(KERN_INFO "%s: Memory squeeze," - "deferring packet.\n", - net_dev->name); - sis_priv->rx_skbuff[entry] = NULL; - /* reset buffer descriptor state */ - sis_priv->rx_ring[entry].cmdsts = 0; - sis_priv->rx_ring[entry].bufptr = 0; - sis_priv->stats.rx_dropped++; - sis_priv->cur_rx++; - break; - } + sis_priv->dirty_rx++; +refill_rx_ring: skb->dev = net_dev; sis_priv->rx_skbuff[entry] = skb; sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; sis_priv->rx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev, skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - sis_priv->dirty_rx++; } sis_priv->cur_rx++; entry = sis_priv->cur_rx % NUM_RX_DESC; -- cgit v1.2.2 From 5efb764c8653c187912669629c14bb47242a5d05 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 24 Apr 2007 12:51:03 -0400 Subject: drivers/net/hamradio/baycom_ser_fdx build fix sparc64: drivers/net/hamradio/baycom_ser_fdx.c: In function `ser12_open': drivers/net/hamradio/baycom_ser_fdx.c:417: error: `NR_IRQS' undeclared (first us e in this function) drivers/net/hamradio/baycom_ser_fdx.c:417: error: (Each undeclared identifier is reported only once drivers/net/hamradio/baycom_ser_fdx.c:417: error: for each function it appears i n.) Cc: Folkert van Heusden Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/hamradio/baycom_ser_fdx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index 59214e74b9cf..30baf6ecfc63 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c @@ -75,12 +75,14 @@ #include #include #include -#include -#include #include #include #include +#include +#include +#include + /* --------------------------------------------------------------------- */ #define BAYCOM_DEBUG -- cgit v1.2.2 From 68c9f75a0539db583db074059d54deb607d1a475 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 24 Apr 2007 15:35:53 -0700 Subject: [BNX2]: Fix occasional NETDEV WATCHDOG on 5709. Tweak a register setting to prevent the tx mailbox from halting. Update version to 1.5.8. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 7 +++++-- drivers/net/bnx2.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0b7aded8dcfd..e85f5ec48f96 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.7" -#define DRV_MODULE_RELDATE "March 29, 2007" +#define DRV_MODULE_VERSION "1.5.8" +#define DRV_MODULE_RELDATE "April 24, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -3421,6 +3421,9 @@ bnx2_init_chip(struct bnx2 *bp) val = REG_RD(bp, BNX2_MQ_CONFIG); val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; + if (CHIP_ID(bp) == CHIP_ID_5709_A0 || CHIP_ID(bp) == CHIP_ID_5709_A1) + val |= BNX2_MQ_CONFIG_HALT_DIS; + REG_WR(bp, BNX2_MQ_CONFIG, val); val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index ccbdf81c6599..878eee58f12a 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6518,6 +6518,7 @@ struct bnx2 { #define CHIP_ID_5708_B0 0x57081000 #define CHIP_ID_5708_B1 0x57081010 #define CHIP_ID_5709_A0 0x57090000 +#define CHIP_ID_5709_A1 0x57090010 #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) -- cgit v1.2.2