diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/7990.c | 6 | ||||
-rw-r--r-- | drivers/net/atlx/atl1.c | 17 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 16 | ||||
-rw-r--r-- | drivers/net/forcedeth.c | 20 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_82598.c | 4 | ||||
-rw-r--r-- | drivers/net/s2io.c | 10 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 4 | ||||
-rw-r--r-- | drivers/net/sky2.c | 2 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 52 |
9 files changed, 93 insertions, 38 deletions
diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 750a46f4bc58..ad6b8a5b6574 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c | |||
@@ -506,6 +506,7 @@ int lance_open (struct net_device *dev) | |||
506 | 506 | ||
507 | return res; | 507 | return res; |
508 | } | 508 | } |
509 | EXPORT_SYMBOL_GPL(lance_open); | ||
509 | 510 | ||
510 | int lance_close (struct net_device *dev) | 511 | int lance_close (struct net_device *dev) |
511 | { | 512 | { |
@@ -521,6 +522,7 @@ int lance_close (struct net_device *dev) | |||
521 | 522 | ||
522 | return 0; | 523 | return 0; |
523 | } | 524 | } |
525 | EXPORT_SYMBOL_GPL(lance_close); | ||
524 | 526 | ||
525 | void lance_tx_timeout(struct net_device *dev) | 527 | void lance_tx_timeout(struct net_device *dev) |
526 | { | 528 | { |
@@ -529,7 +531,7 @@ void lance_tx_timeout(struct net_device *dev) | |||
529 | dev->trans_start = jiffies; | 531 | dev->trans_start = jiffies; |
530 | netif_wake_queue (dev); | 532 | netif_wake_queue (dev); |
531 | } | 533 | } |
532 | 534 | EXPORT_SYMBOL_GPL(lance_tx_timeout); | |
533 | 535 | ||
534 | int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | 536 | int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) |
535 | { | 537 | { |
@@ -586,6 +588,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | |||
586 | 588 | ||
587 | return 0; | 589 | return 0; |
588 | } | 590 | } |
591 | EXPORT_SYMBOL_GPL(lance_start_xmit); | ||
589 | 592 | ||
590 | /* taken from the depca driver via a2065.c */ | 593 | /* taken from the depca driver via a2065.c */ |
591 | static void lance_load_multicast (struct net_device *dev) | 594 | static void lance_load_multicast (struct net_device *dev) |
@@ -654,6 +657,7 @@ void lance_set_multicast (struct net_device *dev) | |||
654 | if (!stopped) | 657 | if (!stopped) |
655 | netif_start_queue (dev); | 658 | netif_start_queue (dev); |
656 | } | 659 | } |
660 | EXPORT_SYMBOL_GPL(lance_set_multicast); | ||
657 | 661 | ||
658 | #ifdef CONFIG_NET_POLL_CONTROLLER | 662 | #ifdef CONFIG_NET_POLL_CONTROLLER |
659 | void lance_poll(struct net_device *dev) | 663 | void lance_poll(struct net_device *dev) |
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 6ddc911e7d15..99e0b4cdc56f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
@@ -637,22 +637,6 @@ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) | |||
637 | } | 637 | } |
638 | 638 | ||
639 | /* | 639 | /* |
640 | * Force the PHY into power saving mode using vendor magic. | ||
641 | */ | ||
642 | #ifdef CONFIG_PM | ||
643 | static void atl1_phy_enter_power_saving(struct atl1_hw *hw) | ||
644 | { | ||
645 | atl1_write_phy_reg(hw, MII_DBG_ADDR, 0); | ||
646 | atl1_write_phy_reg(hw, MII_DBG_DATA, 0x124E); | ||
647 | atl1_write_phy_reg(hw, MII_DBG_ADDR, 2); | ||
648 | atl1_write_phy_reg(hw, MII_DBG_DATA, 0x3000); | ||
649 | atl1_write_phy_reg(hw, MII_DBG_ADDR, 3); | ||
650 | atl1_write_phy_reg(hw, MII_DBG_DATA, 0); | ||
651 | |||
652 | } | ||
653 | #endif | ||
654 | |||
655 | /* | ||
656 | * Resets the PHY and make all config validate | 640 | * Resets the PHY and make all config validate |
657 | * hw - Struct containing variables accessed by shared code | 641 | * hw - Struct containing variables accessed by shared code |
658 | * | 642 | * |
@@ -2860,7 +2844,6 @@ disable_wol: | |||
2860 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; | 2844 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; |
2861 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); | 2845 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); |
2862 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | 2846 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); |
2863 | atl1_phy_enter_power_saving(hw); | ||
2864 | hw->phy_configured = false; | 2847 | hw->phy_configured = false; |
2865 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | 2848 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); |
2866 | exit: | 2849 | exit: |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 287a61918739..faae01dc1c4b 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -1766,16 +1766,20 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) | |||
1766 | mutex_lock(&ehea_bcmc_regs.lock); | 1766 | mutex_lock(&ehea_bcmc_regs.lock); |
1767 | 1767 | ||
1768 | /* Deregister old MAC in pHYP */ | 1768 | /* Deregister old MAC in pHYP */ |
1769 | ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); | 1769 | if (port->state == EHEA_PORT_UP) { |
1770 | if (ret) | 1770 | ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); |
1771 | goto out_upregs; | 1771 | if (ret) |
1772 | goto out_upregs; | ||
1773 | } | ||
1772 | 1774 | ||
1773 | port->mac_addr = cb0->port_mac_addr << 16; | 1775 | port->mac_addr = cb0->port_mac_addr << 16; |
1774 | 1776 | ||
1775 | /* Register new MAC in pHYP */ | 1777 | /* Register new MAC in pHYP */ |
1776 | ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); | 1778 | if (port->state == EHEA_PORT_UP) { |
1777 | if (ret) | 1779 | ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); |
1778 | goto out_upregs; | 1780 | if (ret) |
1781 | goto out_upregs; | ||
1782 | } | ||
1779 | 1783 | ||
1780 | ret = 0; | 1784 | ret = 0; |
1781 | 1785 | ||
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 9eca97fb0a54..2cb244763292 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -3273,6 +3273,20 @@ static void nv_link_irq(struct net_device *dev) | |||
3273 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); | 3273 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); |
3274 | } | 3274 | } |
3275 | 3275 | ||
3276 | static void nv_msi_workaround(struct fe_priv *np) | ||
3277 | { | ||
3278 | |||
3279 | /* Need to toggle the msi irq mask within the ethernet device, | ||
3280 | * otherwise, future interrupts will not be detected. | ||
3281 | */ | ||
3282 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
3283 | u8 __iomem *base = np->base; | ||
3284 | |||
3285 | writel(0, base + NvRegMSIIrqMask); | ||
3286 | writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); | ||
3287 | } | ||
3288 | } | ||
3289 | |||
3276 | static irqreturn_t nv_nic_irq(int foo, void *data) | 3290 | static irqreturn_t nv_nic_irq(int foo, void *data) |
3277 | { | 3291 | { |
3278 | struct net_device *dev = (struct net_device *) data; | 3292 | struct net_device *dev = (struct net_device *) data; |
@@ -3295,6 +3309,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
3295 | if (!(events & np->irqmask)) | 3309 | if (!(events & np->irqmask)) |
3296 | break; | 3310 | break; |
3297 | 3311 | ||
3312 | nv_msi_workaround(np); | ||
3313 | |||
3298 | spin_lock(&np->lock); | 3314 | spin_lock(&np->lock); |
3299 | nv_tx_done(dev); | 3315 | nv_tx_done(dev); |
3300 | spin_unlock(&np->lock); | 3316 | spin_unlock(&np->lock); |
@@ -3410,6 +3426,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) | |||
3410 | if (!(events & np->irqmask)) | 3426 | if (!(events & np->irqmask)) |
3411 | break; | 3427 | break; |
3412 | 3428 | ||
3429 | nv_msi_workaround(np); | ||
3430 | |||
3413 | spin_lock(&np->lock); | 3431 | spin_lock(&np->lock); |
3414 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); | 3432 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); |
3415 | spin_unlock(&np->lock); | 3433 | spin_unlock(&np->lock); |
@@ -3750,6 +3768,8 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) | |||
3750 | if (!(events & NVREG_IRQ_TIMER)) | 3768 | if (!(events & NVREG_IRQ_TIMER)) |
3751 | return IRQ_RETVAL(0); | 3769 | return IRQ_RETVAL(0); |
3752 | 3770 | ||
3771 | nv_msi_workaround(np); | ||
3772 | |||
3753 | spin_lock(&np->lock); | 3773 | spin_lock(&np->lock); |
3754 | np->intr_test = 1; | 3774 | np->intr_test = 1; |
3755 | spin_unlock(&np->lock); | 3775 | spin_unlock(&np->lock); |
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 6321b059ce13..2f38e847e2cd 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c | |||
@@ -58,8 +58,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); | |||
58 | 58 | ||
59 | static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) | 59 | static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) |
60 | { | 60 | { |
61 | hw->mac.num_rx_queues = IXGBE_82598_MAX_TX_QUEUES; | 61 | hw->mac.num_rx_queues = IXGBE_82598_MAX_RX_QUEUES; |
62 | hw->mac.num_tx_queues = IXGBE_82598_MAX_RX_QUEUES; | 62 | hw->mac.num_tx_queues = IXGBE_82598_MAX_TX_QUEUES; |
63 | hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES; | 63 | hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES; |
64 | 64 | ||
65 | /* PHY ops are filled in by default properly for Fiber only */ | 65 | /* PHY ops are filled in by default properly for Fiber only */ |
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index a20693e09ae8..b5c1e663417d 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -2861,7 +2861,8 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget) | |||
2861 | struct config_param *config; | 2861 | struct config_param *config; |
2862 | struct mac_info *mac_control; | 2862 | struct mac_info *mac_control; |
2863 | int pkts_processed = 0; | 2863 | int pkts_processed = 0; |
2864 | u8 *addr = NULL, val8 = 0; | 2864 | u8 __iomem *addr = NULL; |
2865 | u8 val8 = 0; | ||
2865 | struct s2io_nic *nic = dev->priv; | 2866 | struct s2io_nic *nic = dev->priv; |
2866 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | 2867 | struct XENA_dev_config __iomem *bar0 = nic->bar0; |
2867 | int budget_org = budget; | 2868 | int budget_org = budget; |
@@ -2878,7 +2879,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget) | |||
2878 | if (pkts_processed < budget_org) { | 2879 | if (pkts_processed < budget_org) { |
2879 | netif_rx_complete(dev, napi); | 2880 | netif_rx_complete(dev, napi); |
2880 | /*Re Enable MSI-Rx Vector*/ | 2881 | /*Re Enable MSI-Rx Vector*/ |
2881 | addr = (u8 *)&bar0->xmsi_mask_reg; | 2882 | addr = (u8 __iomem *)&bar0->xmsi_mask_reg; |
2882 | addr += 7 - ring->ring_no; | 2883 | addr += 7 - ring->ring_no; |
2883 | val8 = (ring->ring_no == 0) ? 0x3f : 0xbf; | 2884 | val8 = (ring->ring_no == 0) ? 0x3f : 0xbf; |
2884 | writeb(val8, addr); | 2885 | writeb(val8, addr); |
@@ -4364,9 +4365,10 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) | |||
4364 | return IRQ_HANDLED; | 4365 | return IRQ_HANDLED; |
4365 | 4366 | ||
4366 | if (sp->config.napi) { | 4367 | if (sp->config.napi) { |
4367 | u8 *addr = NULL, val8 = 0; | 4368 | u8 __iomem *addr = NULL; |
4369 | u8 val8 = 0; | ||
4368 | 4370 | ||
4369 | addr = (u8 *)&bar0->xmsi_mask_reg; | 4371 | addr = (u8 __iomem *)&bar0->xmsi_mask_reg; |
4370 | addr += (7 - ring->ring_no); | 4372 | addr += (7 - ring->ring_no); |
4371 | val8 = (ring->ring_no == 0) ? 0x7f : 0xff; | 4373 | val8 = (ring->ring_no == 0) ? 0x7f : 0xff; |
4372 | writeb(val8, addr); | 4374 | writeb(val8, addr); |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d3f749c72d41..790db89db345 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -733,8 +733,10 @@ void falcon_fini_rx(struct efx_rx_queue *rx_queue) | |||
733 | continue; | 733 | continue; |
734 | break; | 734 | break; |
735 | } | 735 | } |
736 | if (rc) | 736 | if (rc) { |
737 | EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); | 737 | EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); |
738 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); | ||
739 | } | ||
738 | 740 | ||
739 | /* Remove RX descriptor ring from card */ | 741 | /* Remove RX descriptor ring from card */ |
740 | EFX_ZERO_OWORD(rx_desc_ptr); | 742 | EFX_ZERO_OWORD(rx_desc_ptr); |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3bb60530d4d7..62436b3a18c6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -4404,7 +4404,9 @@ static int sky2_resume(struct pci_dev *pdev) | |||
4404 | if (err) { | 4404 | if (err) { |
4405 | printk(KERN_ERR PFX "%s: could not up: %d\n", | 4405 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
4406 | dev->name, err); | 4406 | dev->name, err); |
4407 | rtnl_lock(); | ||
4407 | dev_close(dev); | 4408 | dev_close(dev); |
4409 | rtnl_unlock(); | ||
4408 | goto out; | 4410 | goto out; |
4409 | } | 4411 | } |
4410 | } | 4412 | } |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 5450eac9e263..4452306d5328 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -44,11 +44,15 @@ struct virtnet_info | |||
44 | /* The skb we couldn't send because buffers were full. */ | 44 | /* The skb we couldn't send because buffers were full. */ |
45 | struct sk_buff *last_xmit_skb; | 45 | struct sk_buff *last_xmit_skb; |
46 | 46 | ||
47 | /* If we need to free in a timer, this is it. */ | ||
48 | struct timer_list xmit_free_timer; | ||
49 | |||
47 | /* Number of input buffers, and max we've ever had. */ | 50 | /* Number of input buffers, and max we've ever had. */ |
48 | unsigned int num, max; | 51 | unsigned int num, max; |
49 | 52 | ||
50 | /* For cleaning up after transmission. */ | 53 | /* For cleaning up after transmission. */ |
51 | struct tasklet_struct tasklet; | 54 | struct tasklet_struct tasklet; |
55 | bool free_in_tasklet; | ||
52 | 56 | ||
53 | /* Receive & send queues. */ | 57 | /* Receive & send queues. */ |
54 | struct sk_buff_head recv; | 58 | struct sk_buff_head recv; |
@@ -72,7 +76,7 @@ static void skb_xmit_done(struct virtqueue *svq) | |||
72 | /* Suppress further interrupts. */ | 76 | /* Suppress further interrupts. */ |
73 | svq->vq_ops->disable_cb(svq); | 77 | svq->vq_ops->disable_cb(svq); |
74 | 78 | ||
75 | /* We were waiting for more output buffers. */ | 79 | /* We were probably waiting for more output buffers. */ |
76 | netif_wake_queue(vi->dev); | 80 | netif_wake_queue(vi->dev); |
77 | 81 | ||
78 | /* Make sure we re-xmit last_xmit_skb: if there are no more packets | 82 | /* Make sure we re-xmit last_xmit_skb: if there are no more packets |
@@ -94,9 +98,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
94 | BUG_ON(len > MAX_PACKET_LEN); | 98 | BUG_ON(len > MAX_PACKET_LEN); |
95 | 99 | ||
96 | skb_trim(skb, len); | 100 | skb_trim(skb, len); |
97 | skb->protocol = eth_type_trans(skb, dev); | 101 | |
98 | pr_debug("Receiving skb proto 0x%04x len %i type %i\n", | ||
99 | ntohs(skb->protocol), skb->len, skb->pkt_type); | ||
100 | dev->stats.rx_bytes += skb->len; | 102 | dev->stats.rx_bytes += skb->len; |
101 | dev->stats.rx_packets++; | 103 | dev->stats.rx_packets++; |
102 | 104 | ||
@@ -106,6 +108,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
106 | goto frame_err; | 108 | goto frame_err; |
107 | } | 109 | } |
108 | 110 | ||
111 | skb->protocol = eth_type_trans(skb, dev); | ||
112 | pr_debug("Receiving skb proto 0x%04x len %i type %i\n", | ||
113 | ntohs(skb->protocol), skb->len, skb->pkt_type); | ||
114 | |||
109 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 115 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
110 | pr_debug("GSO!\n"); | 116 | pr_debug("GSO!\n"); |
111 | switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | 117 | switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
@@ -238,9 +244,25 @@ static void free_old_xmit_skbs(struct virtnet_info *vi) | |||
238 | } | 244 | } |
239 | } | 245 | } |
240 | 246 | ||
247 | /* If the virtio transport doesn't always notify us when all in-flight packets | ||
248 | * are consumed, we fall back to using this function on a timer to free them. */ | ||
249 | static void xmit_free(unsigned long data) | ||
250 | { | ||
251 | struct virtnet_info *vi = (void *)data; | ||
252 | |||
253 | netif_tx_lock(vi->dev); | ||
254 | |||
255 | free_old_xmit_skbs(vi); | ||
256 | |||
257 | if (!skb_queue_empty(&vi->send)) | ||
258 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); | ||
259 | |||
260 | netif_tx_unlock(vi->dev); | ||
261 | } | ||
262 | |||
241 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | 263 | static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) |
242 | { | 264 | { |
243 | int num; | 265 | int num, err; |
244 | struct scatterlist sg[2+MAX_SKB_FRAGS]; | 266 | struct scatterlist sg[2+MAX_SKB_FRAGS]; |
245 | struct virtio_net_hdr *hdr; | 267 | struct virtio_net_hdr *hdr; |
246 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 268 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
@@ -283,7 +305,11 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
283 | vnet_hdr_to_sg(sg, skb); | 305 | vnet_hdr_to_sg(sg, skb); |
284 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; | 306 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; |
285 | 307 | ||
286 | return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); | 308 | err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); |
309 | if (!err && !vi->free_in_tasklet) | ||
310 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); | ||
311 | |||
312 | return err; | ||
287 | } | 313 | } |
288 | 314 | ||
289 | static void xmit_tasklet(unsigned long data) | 315 | static void xmit_tasklet(unsigned long data) |
@@ -295,6 +321,8 @@ static void xmit_tasklet(unsigned long data) | |||
295 | vi->svq->vq_ops->kick(vi->svq); | 321 | vi->svq->vq_ops->kick(vi->svq); |
296 | vi->last_xmit_skb = NULL; | 322 | vi->last_xmit_skb = NULL; |
297 | } | 323 | } |
324 | if (vi->free_in_tasklet) | ||
325 | free_old_xmit_skbs(vi); | ||
298 | netif_tx_unlock_bh(vi->dev); | 326 | netif_tx_unlock_bh(vi->dev); |
299 | } | 327 | } |
300 | 328 | ||
@@ -435,6 +463,10 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
435 | vi->vdev = vdev; | 463 | vi->vdev = vdev; |
436 | vdev->priv = vi; | 464 | vdev->priv = vi; |
437 | 465 | ||
466 | /* If they give us a callback when all buffers are done, we don't need | ||
467 | * the timer. */ | ||
468 | vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); | ||
469 | |||
438 | /* We expect two virtqueues, receive then send. */ | 470 | /* We expect two virtqueues, receive then send. */ |
439 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); | 471 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); |
440 | if (IS_ERR(vi->rvq)) { | 472 | if (IS_ERR(vi->rvq)) { |
@@ -454,6 +486,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
454 | 486 | ||
455 | tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); | 487 | tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); |
456 | 488 | ||
489 | if (!vi->free_in_tasklet) | ||
490 | setup_timer(&vi->xmit_free_timer, xmit_free, (unsigned long)vi); | ||
491 | |||
457 | err = register_netdev(dev); | 492 | err = register_netdev(dev); |
458 | if (err) { | 493 | if (err) { |
459 | pr_debug("virtio_net: registering device failed\n"); | 494 | pr_debug("virtio_net: registering device failed\n"); |
@@ -491,6 +526,9 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
491 | /* Stop all the virtqueues. */ | 526 | /* Stop all the virtqueues. */ |
492 | vdev->config->reset(vdev); | 527 | vdev->config->reset(vdev); |
493 | 528 | ||
529 | if (!vi->free_in_tasklet) | ||
530 | del_timer_sync(&vi->xmit_free_timer); | ||
531 | |||
494 | /* Free our skbs in send and recv queues, if any. */ | 532 | /* Free our skbs in send and recv queues, if any. */ |
495 | while ((skb = __skb_dequeue(&vi->recv)) != NULL) { | 533 | while ((skb = __skb_dequeue(&vi->recv)) != NULL) { |
496 | kfree_skb(skb); | 534 | kfree_skb(skb); |
@@ -514,7 +552,7 @@ static struct virtio_device_id id_table[] = { | |||
514 | static unsigned int features[] = { | 552 | static unsigned int features[] = { |
515 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, | 553 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, |
516 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, | 554 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, |
517 | VIRTIO_NET_F_HOST_ECN, | 555 | VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY, |
518 | }; | 556 | }; |
519 | 557 | ||
520 | static struct virtio_driver virtio_net = { | 558 | static struct virtio_driver virtio_net = { |