diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 20:29:15 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-19 20:29:15 -0800 |
commit | 9eb127cc04c4005c8c0708ce92146d91da862b42 (patch) | |
tree | bebab2c136110edf32d6cf32f898871df9fbb0e6 | |
parent | e32795503de02da4e7e74a5e039cc268f6a0ecfb (diff) | |
parent | 152a2a8b5e1d4cbe91a7c66f1028db15164a3766 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) Really fix tuntap SKB use after free bug, from Eric Dumazet.
2) Adjust SKB data pointer to point past the transport header before
calling icmpv6_notify() so that the headers are in the state which
that function expects. From Duan Jiong.
3) Fix ambiguities in the new tuntap multi-queue APIs. From Jason
Wang.
4) mISDN needs to use del_timer_sync(), from Konstantin Khlebnikov.
5) Don't destroy mutex after freeing up device private in mac802154,
fix also from Konstantin Khlebnikov.
6) Fix INET request socket leak in TCP and DCCP, from Christoph Paasch.
7) SCTP HMAC kconfig rework, from Neil Horman.
8) Fix SCTP jprobes function signature, otherwise things explode, from
Daniel Borkmann.
9) Fix typo in ipv6-offload Makefile variable reference, from Simon
Arlott.
10) Don't fail USBNET open just because remote wakeup isn't supported,
from Oliver Neukum.
11) be2net driver bug fixes from Sathya Perla.
12) SOLOS PCI ATM driver bug fixes from Nathan Williams and David
Woodhouse.
13) Fix MTU changing regression in 8139cp driver, from John Greene.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (45 commits)
solos-pci: ensure all TX packets are aligned to 4 bytes
solos-pci: add firmware upgrade support for new models
solos-pci: remove superfluous debug output
solos-pci: add GPIO support for newer versions on Geos board
8139cp: Prevent dev_close/cp_interrupt race on MTU change
net: qmi_wwan: add ZTE MF880
drivers/net: Use of_match_ptr() macro in smsc911x.c
drivers/net: Use of_match_ptr() macro in smc91x.c
ipv6: addrconf.c: remove unnecessary "if"
bridge: Correctly encode addresses when dumping mdb entries
bridge: Do not unregister all PF_BRIDGE rtnl operations
use generic usbnet_manage_power()
usbnet: generic manage_power()
usbnet: handle PM failure gracefully
ksz884x: fix receive polling race condition
qlcnic: update driver version
qlcnic: fix unused variable warnings
net: fec: forbid FEC_PTP on SoCs that do not support
be2net: fix wrong frag_idx reported by RX CQ
be2net: fix be_close() to ensure all events are ack'ed
...
52 files changed, 545 insertions, 202 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index c909b7b7d5f..d70abe77f73 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -42,7 +42,8 @@ #include <linux/swab.h> #include <linux/slab.h> -#define VERSION "0.07" +#define VERSION "1.04" +#define DRIVER_VERSION 0x01 #define PTAG "solos-pci" #define CONFIG_RAM_SIZE 128 @@ -56,16 +57,21 @@ #define FLASH_BUSY 0x60 #define FPGA_MODE 0x5C #define FLASH_MODE 0x58 +#define GPIO_STATUS 0x54 +#define DRIVER_VER 0x50 #define TX_DMA_ADDR(port) (0x40 + (4 * (port))) #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define DATA_RAM_SIZE 32768 #define BUF_SIZE 2048 #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ -#define FPGA_PAGE 528 /* FPGA flash page size*/ -#define SOLOS_PAGE 512 /* Solos flash page size*/ -#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ -#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ +/* Old boards use ATMEL AD45DB161D flash */ +#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/ +#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/ +#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/ +#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/ +/* Current boards use M25P/M25PE SPI flash */ +#define SPI_FLASH_BLOCK (256 * 64) #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) @@ -122,11 +128,14 @@ struct solos_card { struct sk_buff_head cli_queue[4]; struct sk_buff *tx_skb[4]; struct sk_buff *rx_skb[4]; + unsigned char *dma_bounce; wait_queue_head_t param_wq; wait_queue_head_t fw_wq; int using_dma; + int dma_alignment; int fpga_version; int buffer_size; + int atmel_flash; }; @@ -451,7 +460,6 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, len = skb->len; memcpy(buf, skb->data, len); - dev_dbg(&card->dev->dev, "len: %d\n", len); kfree_skb(skb); return len; @@ -498,6 +506,78 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, return err?:count; } +struct geos_gpio_attr { + struct device_attribute attr; + int offset; +}; + +#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \ + struct geos_gpio_attr gpio_attr_##_name = { \ + .attr = __ATTR(_name, _mode, _show, _store), \ + .offset = _offset } + +static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + if (count != 1 && (count != 2 || buf[1] != '\n')) + return -EINVAL; + + spin_lock_irq(&card->param_queue_lock); + data32 = ioread32(card->config_regs + GPIO_STATUS); + if (buf[0] == '1') { + data32 |= 1 << gattr->offset; + iowrite32(data32, card->config_regs + GPIO_STATUS); + } else if (buf[0] == '0') { + data32 &= ~(1 << gattr->offset); + iowrite32(data32, card->config_regs + GPIO_STATUS); + } else { + count = -EINVAL; + } + spin_lock_irq(&card->param_queue_lock); + return count; +} + +static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + data32 = ioread32(card->config_regs + GPIO_STATUS); + data32 = (data32 >> gattr->offset) & 1; + + return sprintf(buf, "%d\n", data32); +} + +static ssize_t hardware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); + struct solos_card *card = pci_get_drvdata(pdev); + uint32_t data32; + + data32 = ioread32(card->config_regs + GPIO_STATUS); + switch (gattr->offset) { + case 0: + /* HardwareVersion */ + data32 = data32 & 0x1F; + break; + case 1: + /* HardwareVariant */ + data32 = (data32 >> 5) & 0x0F; + break; + } + return sprintf(buf, "%d\n", data32); +} + static DEVICE_ATTR(console, 0644, console_show, console_store); @@ -506,6 +586,14 @@ static DEVICE_ATTR(console, 0644, console_show, console_store); #include "solos-attrlist.c" +static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9); +static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10); +static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11); +static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12); +static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13); +static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14); +static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0); +static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1); #undef SOLOS_ATTR_RO #undef SOLOS_ATTR_RW @@ -522,6 +610,23 @@ static struct attribute_group solos_attr_group = { .name = "parameters", }; +static struct attribute *gpio_attrs[] = { + &gpio_attr_GPIO1.attr.attr, + &gpio_attr_GPIO2.attr.attr, + &gpio_attr_GPIO3.attr.attr, + &gpio_attr_GPIO4.attr.attr, + &gpio_attr_GPIO5.attr.attr, + &gpio_attr_PushButton.attr.attr, + &gpio_attr_HardwareVersion.attr.attr, + &gpio_attr_HardwareVariant.attr.attr, + NULL +}; + +static struct attribute_group gpio_attr_group = { + .attrs = gpio_attrs, + .name = "gpio", +}; + static int flash_upgrade(struct solos_card *card, int chip) { const struct firmware *fw; @@ -533,16 +638,25 @@ static int flash_upgrade(struct solos_card *card, int chip) switch (chip) { case 0: fw_name = "solos-FPGA.bin"; - blocksize = FPGA_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_FPGA_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; break; case 1: fw_name = "solos-Firmware.bin"; - blocksize = SOLOS_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_SOLOS_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; break; case 2: if (card->fpga_version > LEGACY_BUFFERS){ fw_name = "solos-db-FPGA.bin"; - blocksize = FPGA_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_FPGA_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; } else { dev_info(&card->dev->dev, "FPGA version doesn't support" " daughter board upgrades\n"); @@ -552,7 +666,10 @@ static int flash_upgrade(struct solos_card *card, int chip) case 3: if (card->fpga_version > LEGACY_BUFFERS){ fw_name = "solos-Firmware.bin"; - blocksize = SOLOS_BLOCK; + if (card->atmel_flash) + blocksize = ATMEL_SOLOS_BLOCK; + else + blocksize = SPI_FLASH_BLOCK; } else { dev_info(&card->dev->dev, "FPGA version doesn't support" " daughter board upgrades\n"); @@ -568,6 +685,9 @@ static int flash_upgrade(struct solos_card *card, int chip) dev_info(&card->dev->dev, "Flash upgrade starting\n"); + /* New FPGAs require driver version before permitting flash upgrades */ + iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER); + numblocks = fw->size / blocksize; dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size); dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); @@ -597,9 +717,13 @@ static int flash_upgrade(struct solos_card *card, int chip) /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */ iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE); - /* Copy block to buffer, swapping each 16 bits */ + /* Copy block to buffer, swapping each 16 bits for Atmel flash */ for(i = 0; i < blocksize; i += 4) { - uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); + uint32_t word; + if (card->atmel_flash) + word = swahb32p((uint32_t *)(fw->data + offset + i)); + else + word = *(uint32_t *)(fw->data + offset + i); if(card->fpga_version > LEGACY_BUFFERS) iowrite32(word, FLASH_BUF + i); else @@ -961,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card) tx_started |= 1 << port; oldskb = skb; /* We're done with this skb already */ } else if (skb && card->using_dma) { - SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, + unsigned char *data = skb->data; + if ((unsigned long)data & card->dma_alignment) { + data = card->dma_bounce + (BUF_SIZE * port); + memcpy(data, skb->data, skb->len); + } + SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data, skb->len, PCI_DMA_TODEVICE); card->tx_skb[port] = skb; iowrite32(SKB_CB(skb)->dma_addr, @@ -1133,18 +1262,33 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) db_fpga_upgrade = db_firmware_upgrade = 0; } + /* Stopped using Atmel flash after 0.03-38 */ + if (fpga_ver < 39) + card->atmel_flash = 1; + else + card->atmel_flash = 0; + + data32 = ioread32(card->config_regs + PORTS); + card->nr_ports = (data32 & 0x000000FF); + if (card->fpga_version >= DMA_SUPPORTED) { pci_set_master(dev); card->using_dma = 1; + if (1) { /* All known FPGA versions so far */ + card->dma_alignment = 3; + card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL); + if (!card->dma_bounce) { + dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n"); + /* Fallback to MMIO doesn't work */ + goto out_unmap_both; + } + } } else { card->using_dma = 0; /* Set RX empty flag for all ports */ iowrite32(0xF0, card->config_regs + FLAGS_ADDR); } - data32 = ioread32(card->config_regs + PORTS); - card->nr_ports = (data32 & 0x000000FF); - pci_set_drvdata(dev, card); tasklet_init(&card->tlet, solos_bh, (unsigned long)card); @@ -1179,6 +1323,10 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err) goto out_free_irq; + if (card->fpga_version >= DMA_SUPPORTED && + sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group)) + dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n"); + return 0; out_free_irq: @@ -1187,6 +1335,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) tasklet_kill(&card->tlet); out_unmap_both: + kfree(card->dma_bounce); pci_set_drvdata(dev, NULL); pci_iounmap(dev, card->buffers); out_unmap_config: @@ -1289,11 +1438,16 @@ static void fpga_remove(struct pci_dev *dev) iowrite32(1, card->config_regs + FPGA_MODE); (void)ioread32(card->config_regs + FPGA_MODE); + if (card->fpga_version >= DMA_SUPPORTED) + sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group); + atm_remove(card); free_irq(dev->irq, card); tasklet_kill(&card->tlet); + kfree(card->dma_bounce); + /* Release device from reset */ iowrite32(0, card->config_regs + FPGA_MODE); (void)ioread32(card->config_regs + FPGA_MODE); diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 28c99c623bc..22b720ec80c 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -1217,8 +1217,7 @@ static void __exit dsp_cleanup(void) { mISDN_unregister_Bprotocol(&DSP); - if (timer_pending(&dsp_spl_tl)) - del_timer(&dsp_spl_tl); + del_timer_sync(&dsp_spl_tl); if (!list_empty(&dsp_ilist)) { printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not " diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ef2cb241853..b7d45f367d4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4431,8 +4431,6 @@ static void bond_uninit(struct net_device *bond_dev) list_del(&bond->bond_list); - bond_work_cancel_all(bond); - bond_debug_unregister(bond); __hw_addr_flush(&bond->mc_list); diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 0f5917000aa..6433b81256c 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -121,7 +121,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) } irq = irq_of_parse_and_map(np, 0); - if (irq == NO_IRQ) { + if (irq == 0) { dev_err(&ofdev->dev, "no irq found\n"); err = -ENODEV; goto exit_unmap_mem; diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index abf26c7c1d1..3bc1912afba 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -616,7 +616,7 @@ static inline bool be_error(struct be_adapter *adapter) return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; } -static inline bool be_crit_error(struct be_adapter *adapter) +static inline bool be_hw_error(struct be_adapter *adapter) { return adapter->eeh_error || adapter->hw_error; } diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index f2875aa4766..8a250c38fb8 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -298,7 +298,12 @@ void be_async_mcc_enable(struct be_adapter *adapter) void be_async_mcc_disable(struct be_adapter *adapter) { + spin_lock_bh(&adapter->mcc_cq_lock); + adapter->mcc_obj.rearm_cq = false; + be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); + + spin_unlock_bh(&adapter->mcc_cq_lock); } int be_process_mcc(struct be_adapter *adapter) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f95612b907a..9dca22be812 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1689,15 +1689,41 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) struct be_queue_info *rxq = &rxo->q; struct be_queue_info *rx_cq = &rxo->cq; struct be_rx_compl_info *rxcp; + struct be_adapter *adapter = rxo->adapter; + int flush_wait = 0; u16 tail; - /* First cleanup pending rx completions */ - while ((rxcp = be_rx_compl_get(rxo)) != NULL) { - be_rx_compl_discard(rxo, rxcp); - be_cq_notify(rxo->adapter, rx_cq->id, false, 1); + /* Consume pending rx completions. + * Wait for the flush completion (identified by zero num_rcvd) + * to arrive. Notify CQ even when there are no more CQ entries + * for HW to flush partially coalesced CQ entries. + * In Lancer, there is no need to wait for flush compl. + */ + for (;;) { + rxcp = be_rx_compl_get(rxo); + if (rxcp == NULL) { + if (lancer_chip(adapter)) + break; + + if (flush_wait++ > 10 || be_hw_error(adapter)) { + dev_warn(&adapter->pdev->dev, + "did not receive flush compl\n"); + break; + } + be_cq_notify(adapter, rx_cq->id, true, 0); + mdelay(1); + } else { + be_rx_compl_discard(rxo, rxcp); + be_cq_notify(adapter, rx_cq->id, true, 1); + if (rxcp->num_rcvd == 0) + break; + } } - /* Then free posted rx buffer that were not used */ + /* After cleanup, leave the CQ in unarmed state */ + be_cq_notify(adapter, rx_cq->id, false, 0); + + /* Then free posted rx buffers that were not used */ tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { page_info = get_rx_page_info(rxo, tail); @@ -2157,7 +2183,7 @@ void be_detect_error(struct be_adapter *adapter) u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; u32 i; - if (be_crit_error(adapter)) + if (be_hw_error(adapter)) return; if (lancer_chip(adapter)) { @@ -2398,13 +2424,22 @@ static int be_close(struct net_device *netdev) be_roce_dev_close(adapter); - be_async_mcc_disable(adapter); - if (!lancer_chip(adapter)) be_intr_set(adapter, false); - for_all_evt_queues(adapter, eqo, i) { + for_all_evt_queues(adapter, eqo, i) napi_disable(&eqo->napi); + + be_async_mcc_disable(adapter); + + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ + be_tx_compl_clean(adapter); + + be_rx_qs_destroy(adapter); + + for_all_evt_queues(adapter, eqo, i) { if (msix_enabled(adapter)) synchronize_irq(be_msix_vec_get(adapter, eqo)); else @@ -2414,12 +2449,6 @@ static int be_close(struct net_device *netdev) be_irq_unregister(adapter); - /* Wait for all pending tx completions to arrive so that - * all tx skbs are freed. - */ - be_tx_compl_clean(adapter); - - be_rx_qs_destroy(adapter); return 0; } diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 5ba6e1cbd34..ec490d741fc 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -94,9 +94,8 @@ config GIANFAR config FEC_PTP bool "PTP Hardware Clock (PHC)" - depends on FEC && ARCH_MXC + depends on FEC && ARCH_MXC && !SOC_IMX25 && !SOC_IMX27 && !SOC_IMX35 && !SOC_IMX5 select PTP_1588_CLOCK - default y if SOC_IMX6Q --help--- Say Y here if you want to use PTP Hardware Clock (PHC) in the driver. Only the basic clock operations have been implemented. diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 83f0ea929d3..8ebc352bcbe 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -4761,7 +4761,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) struct ksz_dma_buf *dma_buf; struct net_device *dev = NULL; - spin_lock(&hw_priv->hwlock); + spin_lock_irq(&hw_priv->hwlock); last = info->last; while (info->avail < info->alloc) { @@ -4795,7 +4795,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) info->avail++; } info->last = last; - spin_unlock(&hw_priv->hwlock); + spin_unlock_irq(&hw_priv->hwlock); /* Notify the network subsystem that the packet has been sent. */ if (dev) @@ -5259,11 +5259,15 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; + spin_lock(&hw_priv->hwlock); + hw_read_intr(hw, &int_enable); /* Not our interrupt! */ - if (!int_enable) + if (!int_enable) { + spin_unlock(&hw_priv->hwlock); return IRQ_NONE; + } do { hw_ack_intr(hw, int_enable); @@ -5310,6 +5314,8 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) hw_ena_intr(hw); + spin_unlock(&hw_priv->hwlock); + return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 53790247968..bc7ec64e9c7 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 29 -#define QLCNIC_LINUX_VERSIONID "5.0.29" +#define _QLCNIC_LINUX_SUBVERSION 30 +#define QLCNIC_LINUX_VERSIONID "5.0.30" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DR |