diff options
author | David S. Miller <davem@davemloft.net> | 2013-02-08 18:02:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-08 18:02:14 -0500 |
commit | fd5023111cf720db890ef34f305ac5d427e690a0 (patch) | |
tree | 4d21e9a02bfbdafe5fc598af0755db791238dbe7 /drivers/net | |
parent | 8b9a4d56866e0dca6ae886ed9bff777e50d0b70c (diff) | |
parent | 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Synchronize with 'net' in order to sort out some l2tp, wireless, and
ipv6 GRE fixes that will be built on top of in 'net-next'.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 3 | ||||
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/main.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/pub.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/base.c | 7 | ||||
-rw-r--r-- | drivers/net/xen-netback/common.h | 3 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 23 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 115 |
11 files changed, 135 insertions, 86 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 2d7b9377883a..b9dde139dac5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -380,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
380 | } | 380 | } |
381 | } | 381 | } |
382 | 382 | ||
383 | if ((dev_cap->flags & | 383 | if ((dev->caps.flags & |
384 | (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) && | 384 | (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) && |
385 | mlx4_is_master(dev)) | 385 | mlx4_is_master(dev)) |
386 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; | 386 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; |
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index b5ad7eadc4fa..d7115eca5efe 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -1215,6 +1215,9 @@ static const struct usb_device_id cdc_devs[] = { | |||
1215 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), | 1215 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), |
1216 | .driver_info = (unsigned long)&wwan_info, | 1216 | .driver_info = (unsigned long)&wwan_info, |
1217 | }, | 1217 | }, |
1218 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76), | ||
1219 | .driver_info = (unsigned long)&wwan_info, | ||
1220 | }, | ||
1218 | 1221 | ||
1219 | /* Infineon(now Intel) HSPA Modem platform */ | 1222 | /* Infineon(now Intel) HSPA Modem platform */ |
1220 | { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, | 1223 | { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2ca7f8ea2dca..c8e05e27f38c 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -351,6 +351,10 @@ static const struct usb_device_id products[] = { | |||
351 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), | 351 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), |
352 | .driver_info = (unsigned long)&qmi_wwan_info, | 352 | .driver_info = (unsigned long)&qmi_wwan_info, |
353 | }, | 353 | }, |
354 | { /* HUAWEI_INTERFACE_NDIS_CONTROL_QUALCOMM */ | ||
355 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), | ||
356 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
357 | }, | ||
354 | 358 | ||
355 | /* 2. Combined interface devices matching on class+protocol */ | 359 | /* 2. Combined interface devices matching on class+protocol */ |
356 | { /* Huawei E367 and possibly others in "Windows mode" */ | 360 | { /* Huawei E367 and possibly others in "Windows mode" */ |
@@ -361,6 +365,14 @@ static const struct usb_device_id products[] = { | |||
361 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), | 365 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), |
362 | .driver_info = (unsigned long)&qmi_wwan_info, | 366 | .driver_info = (unsigned long)&qmi_wwan_info, |
363 | }, | 367 | }, |
368 | { /* HUAWEI_NDIS_SINGLE_INTERFACE_VDF */ | ||
369 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x37), | ||
370 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
371 | }, | ||
372 | { /* HUAWEI_INTERFACE_NDIS_HW_QUALCOMM */ | ||
373 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x67), | ||
374 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
375 | }, | ||
364 | { /* Pantech UML290, P4200 and more */ | 376 | { /* Pantech UML290, P4200 and more */ |
365 | USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), | 377 | USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), |
366 | .driver_info = (unsigned long)&qmi_wwan_info, | 378 | .driver_info = (unsigned long)&qmi_wwan_info, |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index b1dd5600fd02..c6451c61407a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | 37 | ||
38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ | 38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ |
39 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ | ||
39 | 40 | ||
40 | /* Flags we support */ | 41 | /* Flags we support */ |
41 | #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ | 42 | #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ |
@@ -712,16 +713,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) | |||
712 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); | 713 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); |
713 | } | 714 | } |
714 | 715 | ||
716 | static bool brcms_tx_flush_completed(struct brcms_info *wl) | ||
717 | { | ||
718 | bool result; | ||
719 | |||
720 | spin_lock_bh(&wl->lock); | ||
721 | result = brcms_c_tx_flush_completed(wl->wlc); | ||
722 | spin_unlock_bh(&wl->lock); | ||
723 | return result; | ||
724 | } | ||
725 | |||
715 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) | 726 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) |
716 | { | 727 | { |
717 | struct brcms_info *wl = hw->priv; | 728 | struct brcms_info *wl = hw->priv; |
729 | int ret; | ||
718 | 730 | ||
719 | no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); | 731 | no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); |
720 | 732 | ||
721 | /* wait for packet queue and dma fifos to run empty */ | 733 | ret = wait_event_timeout(wl->tx_flush_wq, |
722 | spin_lock_bh(&wl->lock); | 734 | brcms_tx_flush_completed(wl), |
723 | brcms_c_wait_for_tx_completion(wl->wlc, drop); | 735 | msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT)); |
724 | spin_unlock_bh(&wl->lock); | 736 | |
737 | brcms_dbg_mac80211(wl->wlc->hw->d11core, | ||
738 | "ret=%d\n", jiffies_to_msecs(ret)); | ||
725 | } | 739 | } |
726 | 740 | ||
727 | static const struct ieee80211_ops brcms_ops = { | 741 | static const struct ieee80211_ops brcms_ops = { |
@@ -776,6 +790,7 @@ void brcms_dpc(unsigned long data) | |||
776 | 790 | ||
777 | done: | 791 | done: |
778 | spin_unlock_bh(&wl->lock); | 792 | spin_unlock_bh(&wl->lock); |
793 | wake_up(&wl->tx_flush_wq); | ||
779 | } | 794 | } |
780 | 795 | ||
781 | /* | 796 | /* |
@@ -1024,6 +1039,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1024 | 1039 | ||
1025 | atomic_set(&wl->callbacks, 0); | 1040 | atomic_set(&wl->callbacks, 0); |
1026 | 1041 | ||
1042 | init_waitqueue_head(&wl->tx_flush_wq); | ||
1043 | |||
1027 | /* setup the bottom half handler */ | 1044 | /* setup the bottom half handler */ |
1028 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); | 1045 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); |
1029 | 1046 | ||
@@ -1613,13 +1630,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl) | |||
1613 | spin_lock_bh(&wl->lock); | 1630 | spin_lock_bh(&wl->lock); |
1614 | return blocked; | 1631 | return blocked; |
1615 | } | 1632 | } |
1616 | |||
1617 | /* | ||
1618 | * precondition: perimeter lock has been acquired | ||
1619 | */ | ||
1620 | void brcms_msleep(struct brcms_info *wl, uint ms) | ||
1621 | { | ||
1622 | spin_unlock_bh(&wl->lock); | ||
1623 | msleep(ms); | ||
1624 | spin_lock_bh(&wl->lock); | ||
1625 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 9358bd5ebd35..947ccacf43e6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -68,6 +68,8 @@ struct brcms_info { | |||
68 | spinlock_t lock; /* per-device perimeter lock */ | 68 | spinlock_t lock; /* per-device perimeter lock */ |
69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ | 69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ |
70 | 70 | ||
71 | /* tx flush */ | ||
72 | wait_queue_head_t tx_flush_wq; | ||
71 | 73 | ||
72 | /* timer related fields */ | 74 | /* timer related fields */ |
73 | atomic_t callbacks; /* # outstanding callback functions */ | 75 | atomic_t callbacks; /* # outstanding callback functions */ |
@@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, | |||
100 | extern void brcms_free_timer(struct brcms_timer *timer); | 102 | extern void brcms_free_timer(struct brcms_timer *timer); |
101 | extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); | 103 | extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); |
102 | extern bool brcms_del_timer(struct brcms_timer *timer); | 104 | extern bool brcms_del_timer(struct brcms_timer *timer); |
103 | extern void brcms_msleep(struct brcms_info *wl, uint ms); | ||
104 | extern void brcms_dpc(unsigned long data); | 105 | extern void brcms_dpc(unsigned long data); |
105 | extern void brcms_timer(struct brcms_timer *t); | 106 | extern void brcms_timer(struct brcms_timer *t); |
106 | extern void brcms_fatal_error(struct brcms_info *wl); | 107 | extern void brcms_fatal_error(struct brcms_info *wl); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 8d560b64516d..62be5502b95d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -7510,25 +7510,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) | |||
7510 | return wlc->band->bandunit; | 7510 | return wlc->band->bandunit; |
7511 | } | 7511 | } |
7512 | 7512 | ||
7513 | void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) | 7513 | bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc) |
7514 | { | 7514 | { |
7515 | int timeout = 20; | ||
7516 | int i; | 7515 | int i; |
7517 | 7516 | ||
7518 | /* Kick DMA to send any pending AMPDU */ | 7517 | /* Kick DMA to send any pending AMPDU */ |
7519 | for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) | 7518 | for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) |
7520 | if (wlc->hw->di[i]) | 7519 | if (wlc->hw->di[i]) |
7521 | dma_txflush(wlc->hw->di[i]); | 7520 | dma_kick_tx(wlc->hw->di[i]); |
7522 | 7521 | ||
7523 | /* wait for queue and DMA fifos to run dry */ | 7522 | return !brcms_txpktpendtot(wlc); |
7524 | while (brcms_txpktpendtot(wlc) > 0) { | ||
7525 | brcms_msleep(wlc->wl, 1); | ||
7526 | |||
7527 | if (--timeout == 0) | ||
7528 | break; | ||
7529 | } | ||
7530 | |||
7531 | WARN_ON_ONCE(timeout == 0); | ||
7532 | } | 7523 | } |
7533 | 7524 | ||
7534 | void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) | 7525 | void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 4fb2834f4e64..b0f14b7b8616 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); | |||
314 | extern void brcms_c_scan_start(struct brcms_c_info *wlc); | 314 | extern void brcms_c_scan_start(struct brcms_c_info *wlc); |
315 | extern void brcms_c_scan_stop(struct brcms_c_info *wlc); | 315 | extern void brcms_c_scan_stop(struct brcms_c_info *wlc); |
316 | extern int brcms_c_get_curband(struct brcms_c_info *wlc); | 316 | extern int brcms_c_get_curband(struct brcms_c_info *wlc); |
317 | extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, | ||
318 | bool drop); | ||
319 | extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); | 317 | extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); |
320 | extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); | 318 | extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); |
321 | extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, | 319 | extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, |
@@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); | |||
332 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); | 330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); |
333 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); | 331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); |
334 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); | 332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); |
333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); | ||
335 | 334 | ||
336 | #endif /* _BRCM_PUB_H_ */ | 335 | #endif /* _BRCM_PUB_H_ */ |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 4494d130b37c..0f8b05185eda 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1004 | is_tx ? "Tx" : "Rx"); | 1004 | is_tx ? "Tx" : "Rx"); |
1005 | 1005 | ||
1006 | if (is_tx) { | 1006 | if (is_tx) { |
1007 | rtl_lps_leave(hw); | 1007 | schedule_work(&rtlpriv-> |
1008 | works.lps_leave_work); | ||
1008 | ppsc->last_delaylps_stamp_jiffies = | 1009 | ppsc->last_delaylps_stamp_jiffies = |
1009 | jiffies; | 1010 | jiffies; |
1010 | } | 1011 | } |
@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1014 | } | 1015 | } |
1015 | } else if (ETH_P_ARP == ether_type) { | 1016 | } else if (ETH_P_ARP == ether_type) { |
1016 | if (is_tx) { | 1017 | if (is_tx) { |
1017 | rtl_lps_leave(hw); | 1018 | schedule_work(&rtlpriv->works.lps_leave_work); |
1018 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1019 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1019 | } | 1020 | } |
1020 | 1021 | ||
@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1024 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); | 1025 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); |
1025 | 1026 | ||
1026 | if (is_tx) { | 1027 | if (is_tx) { |
1027 | rtl_lps_leave(hw); | 1028 | schedule_work(&rtlpriv->works.lps_leave_work); |
1028 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1029 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1029 | } | 1030 | } |
1030 | 1031 | ||
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 94b79c3338c4..9d7f1723dd8f 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); | |||
151 | /* Notify xenvif that ring now has space to send an skb to the frontend */ | 151 | /* Notify xenvif that ring now has space to send an skb to the frontend */ |
152 | void xenvif_notify_tx_completion(struct xenvif *vif); | 152 | void xenvif_notify_tx_completion(struct xenvif *vif); |
153 | 153 | ||
154 | /* Prevent the device from generating any further traffic. */ | ||
155 | void xenvif_carrier_off(struct xenvif *vif); | ||
156 | |||
154 | /* Returns number of ring slots required to send an skb to the frontend */ | 157 | /* Returns number of ring slots required to send an skb to the frontend */ |
155 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); | 158 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); |
156 | 159 | ||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index f733cae3d4b6..fc1b8d78f4bc 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -345,17 +345,22 @@ err: | |||
345 | return err; | 345 | return err; |
346 | } | 346 | } |
347 | 347 | ||
348 | void xenvif_disconnect(struct xenvif *vif) | 348 | void xenvif_carrier_off(struct xenvif *vif) |
349 | { | 349 | { |
350 | struct net_device *dev = vif->dev; | 350 | struct net_device *dev = vif->dev; |
351 | if (netif_carrier_ok(dev)) { | 351 | |
352 | rtnl_lock(); | 352 | rtnl_lock(); |
353 | netif_carrier_off(dev); /* discard queued packets */ | 353 | netif_carrier_off(dev); /* discard queued packets */ |
354 | if (netif_running(dev)) | 354 | if (netif_running(dev)) |
355 | xenvif_down(vif); | 355 | xenvif_down(vif); |
356 | rtnl_unlock(); | 356 | rtnl_unlock(); |
357 | xenvif_put(vif); | 357 | xenvif_put(vif); |
358 | } | 358 | } |
359 | |||
360 | void xenvif_disconnect(struct xenvif *vif) | ||
361 | { | ||
362 | if (netif_carrier_ok(vif->dev)) | ||
363 | xenvif_carrier_off(vif); | ||
359 | 364 | ||
360 | atomic_dec(&vif->refcnt); | 365 | atomic_dec(&vif->refcnt); |
361 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); | 366 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f2d6b78d901d..2b9520c46e97 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) | |||
147 | atomic_dec(&netbk->netfront_count); | 147 | atomic_dec(&netbk->netfront_count); |
148 | } | 148 | } |
149 | 149 | ||
150 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); | 150 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, |
151 | u8 status); | ||
151 | static void make_tx_response(struct xenvif *vif, | 152 | static void make_tx_response(struct xenvif *vif, |
152 | struct xen_netif_tx_request *txp, | 153 | struct xen_netif_tx_request *txp, |
153 | s8 st); | 154 | s8 st); |
@@ -879,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif, | |||
879 | 880 | ||
880 | do { | 881 | do { |
881 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | 882 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); |
882 | if (cons >= end) | 883 | if (cons == end) |
883 | break; | 884 | break; |
884 | txp = RING_GET_REQUEST(&vif->tx, cons++); | 885 | txp = RING_GET_REQUEST(&vif->tx, cons++); |
885 | } while (1); | 886 | } while (1); |
@@ -888,6 +889,13 @@ static void netbk_tx_err(struct xenvif *vif, | |||
888 | xenvif_put(vif); | 889 | xenvif_put(vif); |
889 | } | 890 | } |
890 | 891 | ||
892 | static void netbk_fatal_tx_err(struct xenvif *vif) | ||
893 | { | ||
894 | netdev_err(vif->dev, "fatal error; disabling device\n"); | ||
895 | xenvif_carrier_off(vif); | ||
896 | xenvif_put(vif); | ||
897 | } | ||
898 | |||
891 | static int netbk_count_requests(struct xenvif *vif, | 899 | static int netbk_count_requests(struct xenvif *vif, |
892 | struct xen_netif_tx_request *first, | 900 | struct xen_netif_tx_request *first, |
893 | struct xen_netif_tx_request *txp, | 901 | struct xen_netif_tx_request *txp, |
@@ -901,19 +909,22 @@ static int netbk_count_requests(struct xenvif *vif, | |||
901 | 909 | ||
902 | do { | 910 | do { |
903 | if (frags >= work_to_do) { | 911 | if (frags >= work_to_do) { |
904 | netdev_dbg(vif->dev, "Need more frags\n"); | 912 | netdev_err(vif->dev, "Need more frags\n"); |
913 | netbk_fatal_tx_err(vif); | ||
905 | return -frags; | 914 | return -frags; |
906 | } | 915 | } |
907 | 916 | ||
908 | if (unlikely(frags >= MAX_SKB_FRAGS)) { | 917 | if (unlikely(frags >= MAX_SKB_FRAGS)) { |
909 | netdev_dbg(vif->dev, "Too many frags\n"); | 918 | netdev_err(vif->dev, "Too many frags\n"); |
919 | netbk_fatal_tx_err(vif); | ||
910 | return -frags; | 920 | return -frags; |
911 | } | 921 | } |
912 | 922 | ||
913 | memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), | 923 | memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), |
914 | sizeof(*txp)); | 924 | sizeof(*txp)); |
915 | if (txp->size > first->size) { | 925 | if (txp->size > first->size) { |
916 | netdev_dbg(vif->dev, "Frags galore\n"); | 926 | netdev_err(vif->dev, "Frag is bigger than frame.\n"); |
927 | netbk_fatal_tx_err(vif); | ||
917 | return -frags; | 928 | return -frags; |
918 | } | 929 | } |
919 | 930 | ||
@@ -921,8 +932,9 @@ static int netbk_count_requests(struct xenvif *vif, | |||
921 | frags++; | 932 | frags++; |
922 | 933 | ||
923 | if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { | 934 | if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { |
924 | netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", | 935 | netdev_err(vif->dev, "txp->offset: %x, size: %u\n", |
925 | txp->offset, txp->size); | 936 | txp->offset, txp->size); |
937 | netbk_fatal_tx_err(vif); | ||
926 | return -frags; | 938 | return -frags; |
927 | } | 939 | } |
928 | } while ((txp++)->flags & XEN_NETTXF_more_data); | 940 | } while ((txp++)->flags & XEN_NETTXF_more_data); |
@@ -966,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
966 | pending_idx = netbk->pending_ring[index]; | 978 | pending_idx = netbk->pending_ring[index]; |
967 | page = xen_netbk_alloc_page(netbk, skb, pending_idx); | 979 | page = xen_netbk_alloc_page(netbk, skb, pending_idx); |
968 | if (!page) | 980 | if (!page) |
969 | return NULL; | 981 | goto err; |
970 | 982 | ||
971 | gop->source.u.ref = txp->gref; | 983 | gop->source.u.ref = txp->gref; |
972 | gop->source.domid = vif->domid; | 984 | gop->source.domid = vif->domid; |
@@ -988,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
988 | } | 1000 | } |
989 | 1001 | ||
990 | return gop; | 1002 | return gop; |
1003 | err: | ||
1004 | /* Unwind, freeing all pages and sending error responses. */ | ||
1005 | while (i-- > start) { | ||
1006 | xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), | ||
1007 | XEN_NETIF_RSP_ERROR); | ||
1008 | } | ||
1009 | /* The head too, if necessary. */ | ||
1010 | if (start) | ||
1011 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); | ||
1012 | |||
1013 | return NULL; | ||
991 | } | 1014 | } |
992 | 1015 | ||
993 | static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | 1016 | static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, |
@@ -996,30 +1019,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
996 | { | 1019 | { |
997 | struct gnttab_copy *gop = *gopp; | 1020 | struct gnttab_copy *gop = *gopp; |
998 | u16 pending_idx = *((u16 *)skb->data); | 1021 | u16 pending_idx = *((u16 *)skb->data); |
999 | struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; | ||
1000 | struct xenvif *vif = pending_tx_info[pending_idx].vif; | ||
1001 | struct xen_netif_tx_request *txp; | ||
1002 | struct skb_shared_info *shinfo = skb_shinfo(skb); | 1022 | struct skb_shared_info *shinfo = skb_shinfo(skb); |
1003 | int nr_frags = shinfo->nr_frags; | 1023 | int nr_frags = shinfo->nr_frags; |
1004 | int i, err, start; | 1024 | int i, err, start; |
1005 | 1025 | ||
1006 | /* Check status of header. */ | 1026 | /* Check status of header. */ |
1007 | err = gop->status; | 1027 | err = gop->status; |
1008 | if (unlikely(err)) { | 1028 | if (unlikely(err)) |
1009 | pending_ring_idx_t index; | 1029 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); |
1010 | index = pending_index(netbk->pending_prod++); | ||
1011 | txp = &pending_tx_info[pending_idx].req; | ||
1012 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | ||
1013 | netbk->pending_ring[index] = pending_idx; | ||
1014 | xenvif_put(vif); | ||
1015 | } | ||
1016 | 1030 | ||
1017 | /* Skip first skb fragment if it is on same page as header fragment. */ | 1031 | /* Skip first skb fragment if it is on same page as header fragment. */ |
1018 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); | 1032 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); |
1019 | 1033 | ||
1020 | for (i = start; i < nr_frags; i++) { | 1034 | for (i = start; i < nr_frags; i++) { |
1021 | int j, newerr; | 1035 | int j, newerr; |
1022 | pending_ring_idx_t index; | ||
1023 | 1036 | ||
1024 | pending_idx = frag_get_pending_idx(&shinfo->frags[i]); | 1037 | pending_idx = frag_get_pending_idx(&shinfo->frags[i]); |
1025 | 1038 | ||
@@ -1028,16 +1041,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1028 | if (likely(!newerr)) { | 1041 | if (likely(!newerr)) { |
1029 | /* Had a previous error? Invalidate this fragment. */ | 1042 | /* Had a previous error? Invalidate this fragment. */ |
1030 | if (unlikely(err)) | 1043 | if (unlikely(err)) |
1031 | xen_netbk_idx_release(netbk, pending_idx); | 1044 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1032 | continue; | 1045 | continue; |
1033 | } | 1046 | } |
1034 | 1047 | ||
1035 | /* Error on this fragment: respond to client with an error. */ | 1048 | /* Error on this fragment: respond to client with an error. */ |
1036 | txp = &netbk->pending_tx_info[pending_idx].req; | 1049 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); |
1037 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | ||
1038 | index = pending_index(netbk->pending_prod++); | ||
1039 | netbk->pending_ring[index] = pending_idx; | ||
1040 | xenvif_put(vif); | ||
1041 | 1050 | ||
1042 | /* Not the first error? Preceding frags already invalidated. */ | 1051 | /* Not the first error? Preceding frags already invalidated. */ |
1043 | if (err) | 1052 | if (err) |
@@ -1045,10 +1054,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1045 | 1054 | ||
1046 | /* First error: invalidate header and preceding fragments. */ | 1055 | /* First error: invalidate header and preceding fragments. */ |
1047 | pending_idx = *((u16 *)skb->data); | 1056 | pending_idx = *((u16 *)skb->data); |
1048 | xen_netbk_idx_release(netbk, pending_idx); | 1057 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1049 | for (j = start; j < i; j++) { | 1058 | for (j = start; j < i; j++) { |
1050 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | 1059 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); |
1051 | xen_netbk_idx_release(netbk, pending_idx); | 1060 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1052 | } | 1061 | } |
1053 | 1062 | ||
1054 | /* Remember the error: invalidate all subsequent fragments. */ | 1063 | /* Remember the error: invalidate all subsequent fragments. */ |
@@ -1082,7 +1091,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) | |||
1082 | 1091 | ||
1083 | /* Take an extra reference to offset xen_netbk_idx_release */ | 1092 | /* Take an extra reference to offset xen_netbk_idx_release */ |
1084 | get_page(netbk->mmap_pages[pending_idx]); | 1093 | get_page(netbk->mmap_pages[pending_idx]); |
1085 | xen_netbk_idx_release(netbk, pending_idx); | 1094 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1086 | } | 1095 | } |
1087 | } | 1096 | } |
1088 | 1097 | ||
@@ -1095,7 +1104,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, | |||
1095 | 1104 | ||
1096 | do { | 1105 | do { |
1097 | if (unlikely(work_to_do-- <= 0)) { | 1106 | if (unlikely(work_to_do-- <= 0)) { |
1098 | netdev_dbg(vif->dev, "Missing extra info\n"); | 1107 | netdev_err(vif->dev, "Missing extra info\n"); |
1108 | netbk_fatal_tx_err(vif); | ||
1099 | return -EBADR; | 1109 | return -EBADR; |
1100 | } | 1110 | } |
1101 | 1111 | ||
@@ -1104,8 +1114,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, | |||
1104 | if (unlikely(!extra.type || | 1114 | if (unlikely(!extra.type || |
1105 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { | 1115 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { |
1106 | vif->tx.req_cons = ++cons; | 1116 | vif->tx.req_cons = ++cons; |
1107 | netdev_dbg(vif->dev, | 1117 | netdev_err(vif->dev, |
1108 | "Invalid extra type: %d\n", extra.type); | 1118 | "Invalid extra type: %d\n", extra.type); |
1119 | netbk_fatal_tx_err(vif); | ||
1109 | return -EINVAL; | 1120 | return -EINVAL; |
1110 | } | 1121 | } |
1111 | 1122 | ||
@@ -1121,13 +1132,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, | |||
1121 | struct xen_netif_extra_info *gso) | 1132 | struct xen_netif_extra_info *gso) |
1122 | { | 1133 | { |
1123 | if (!gso->u.gso.size) { | 1134 | if (!gso->u.gso.size) { |
1124 | netdev_dbg(vif->dev, "GSO size must not be zero.\n"); | 1135 | netdev_err(vif->dev, "GSO size must not be zero.\n"); |
1136 | netbk_fatal_tx_err(vif); | ||
1125 | return -EINVAL; | 1137 | return -EINVAL; |
1126 | } | 1138 | } |
1127 | 1139 | ||
1128 | /* Currently only TCPv4 S.O. is supported. */ | 1140 | /* Currently only TCPv4 S.O. is supported. */ |
1129 | if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { | 1141 | if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { |
1130 | netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); | 1142 | netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); |
1143 | netbk_fatal_tx_err(vif); | ||
1131 | return -EINVAL; | 1144 | return -EINVAL; |
1132 | } | 1145 | } |
1133 | 1146 | ||
@@ -1264,9 +1277,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1264 | 1277 | ||
1265 | /* Get a netif from the list with work to do. */ | 1278 | /* Get a netif from the list with work to do. */ |
1266 | vif = poll_net_schedule_list(netbk); | 1279 | vif = poll_net_schedule_list(netbk); |
1280 | /* This can sometimes happen because the test of | ||
1281 | * list_empty(net_schedule_list) at the top of the | ||
1282 | * loop is unlocked. Just go back and have another | ||
1283 | * look. | ||
1284 | */ | ||
1267 | if (!vif) | 1285 | if (!vif) |
1268 | continue; | 1286 | continue; |
1269 | 1287 | ||
1288 | if (vif->tx.sring->req_prod - vif->tx.req_cons > | ||
1289 | XEN_NETIF_TX_RING_SIZE) { | ||
1290 | netdev_err(vif->dev, | ||
1291 | "Impossible number of requests. " | ||
1292 | "req_prod %d, req_cons %d, size %ld\n", | ||
1293 | vif->tx.sring->req_prod, vif->tx.req_cons, | ||
1294 | XEN_NETIF_TX_RING_SIZE); | ||
1295 | netbk_fatal_tx_err(vif); | ||
1296 | continue; | ||
1297 | } | ||
1298 | |||
1270 | RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); | 1299 | RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); |
1271 | if (!work_to_do) { | 1300 | if (!work_to_do) { |
1272 | xenvif_put(vif); | 1301 | xenvif_put(vif); |
@@ -1294,17 +1323,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1294 | work_to_do = xen_netbk_get_extras(vif, extras, | 1323 | work_to_do = xen_netbk_get_extras(vif, extras, |
1295 | work_to_do); | 1324 | work_to_do); |
1296 | idx = vif->tx.req_cons; | 1325 | idx = vif->tx.req_cons; |
1297 | if (unlikely(work_to_do < 0)) { | 1326 | if (unlikely(work_to_do < 0)) |
1298 | netbk_tx_err(vif, &txreq, idx); | ||
1299 | continue; | 1327 | continue; |
1300 | } | ||
1301 | } | 1328 | } |
1302 | 1329 | ||
1303 | ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); | 1330 | ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); |
1304 | if (unlikely(ret < 0)) { | 1331 | if (unlikely(ret < 0)) |
1305 | netbk_tx_err(vif, &txreq, idx - ret); | ||
1306 | continue; | 1332 | continue; |
1307 | } | 1333 | |
1308 | idx += ret; | 1334 | idx += ret; |
1309 | 1335 | ||
1310 | if (unlikely(txreq.size < ETH_HLEN)) { | 1336 | if (unlikely(txreq.size < ETH_HLEN)) { |
@@ -1316,11 +1342,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1316 | 1342 | ||
1317 | /* No crossing a page as the payload mustn't fragment. */ | 1343 | /* No crossing a page as the payload mustn't fragment. */ |
1318 | if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { | 1344 | if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { |
1319 | netdev_dbg(vif->dev, | 1345 | netdev_err(vif->dev, |
1320 | "txreq.offset: %x, size: %u, end: %lu\n", | 1346 | "txreq.offset: %x, size: %u, end: %lu\n", |
1321 | txreq.offset, txreq.size, | 1347 | txreq.offset, txreq.size, |
1322 | (txreq.offset&~PAGE_MASK) + txreq.size); | 1348 | (txreq.offset&~PAGE_MASK) + txreq.size); |
1323 | netbk_tx_err(vif, &txreq, idx); | 1349 | netbk_fatal_tx_err(vif); |
1324 | continue; | 1350 | continue; |
1325 | } | 1351 | } |
1326 | 1352 | ||
@@ -1348,8 +1374,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1348 | gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; | 1374 | gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; |
1349 | 1375 | ||
1350 | if (netbk_set_skb_gso(vif, skb, gso)) { | 1376 | if (netbk_set_skb_gso(vif, skb, gso)) { |
1377 | /* Failure in netbk_set_skb_gso is fatal. */ | ||
1351 | kfree_skb(skb); | 1378 | kfree_skb(skb); |
1352 | netbk_tx_err(vif, &txreq, idx); | ||
1353 | continue; | 1379 | continue; |
1354 | } | 1380 | } |
1355 | } | 1381 | } |
@@ -1448,7 +1474,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) | |||
1448 | txp->size -= data_len; | 1474 | txp->size -= data_len; |
1449 | } else { | 1475 | } else { |
1450 | /* Schedule a response immediately. */ | 1476 | /* Schedule a response immediately. */ |
1451 | xen_netbk_idx_release(netbk, pending_idx); | 1477 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1452 | } | 1478 | } |
1453 | 1479 | ||
1454 | if (txp->flags & XEN_NETTXF_csum_blank) | 1480 | if (txp->flags & XEN_NETTXF_csum_blank) |
@@ -1500,7 +1526,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) | |||
1500 | xen_netbk_tx_submit(netbk); | 1526 | xen_netbk_tx_submit(netbk); |
1501 | } | 1527 | } |
1502 | 1528 | ||
1503 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | 1529 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, |
1530 | u8 status) | ||
1504 | { | 1531 | { |
1505 | struct xenvif *vif; | 1532 | struct xenvif *vif; |
1506 | struct pending_tx_info *pending_tx_info; | 1533 | struct pending_tx_info *pending_tx_info; |
@@ -1514,7 +1541,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | |||
1514 | 1541 | ||
1515 | vif = pending_tx_info->vif; | 1542 | vif = pending_tx_info->vif; |
1516 | 1543 | ||
1517 | make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); | 1544 | make_tx_response(vif, &pending_tx_info->req, status); |
1518 | 1545 | ||
1519 | index = pending_index(netbk->pending_prod++); | 1546 | index = pending_index(netbk->pending_prod++); |
1520 | netbk->pending_ring[index] = pending_idx; | 1547 | netbk->pending_ring[index] = pending_idx; |