From 88149db4948ef90cf6220d76e34955e46c2ff9f9 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 26 Sep 2011 14:19:47 +0200 Subject: Bluetooth: rfcomm: Fix sleep in invalid context in rfcomm_security_cfm This was triggered by turning off encryption on ACL link when rfcomm was using high security. rfcomm_security_cfm (which is called from rx task) was closing DLC and this involves sending disconnect message (and locking socket). Move closing DLC to rfcomm_process_dlcs and only flag DLC for closure in rfcomm_security_cfm. BUG: sleeping function called from invalid context at net/core/sock.c:2032 in_atomic(): 1, irqs_disabled(): 0, pid: 1788, name: kworker/0:3 [] (unwind_backtrace+0x0/0x108) from [] (dump_stack+0x20/0x24) [] (dump_stack+0x20/0x24) from [] (__might_sleep+0x110/0x12c) [] (__might_sleep+0x110/0x12c) from [] (lock_sock_nested+0x2c/0x64) [] (lock_sock_nested+0x2c/0x64) from [] (l2cap_sock_sendmsg+0x58/0xcc) [] (l2cap_sock_sendmsg+0x58/0xcc) from [] (sock_sendmsg+0xb0/0xd0) [] (sock_sendmsg+0xb0/0xd0) from [] (kernel_sendmsg+0x3c/0x44) [] (kernel_sendmsg+0x3c/0x44) from [] (rfcomm_send_frame+0x50/0x58) [] (rfcomm_send_frame+0x50/0x58) from [] (rfcomm_send_disc+0x78/0x80) [] (rfcomm_send_disc+0x78/0x80) from [] (__rfcomm_dlc_close+0x2d0/0x2fc) [] (__rfcomm_dlc_close+0x2d0/0x2fc) from [] (rfcomm_security_cfm+0x140/0x1e0) [] (rfcomm_security_cfm+0x140/0x1e0) from [] (hci_event_packet+0x1ce8/0x4d84) [] (hci_event_packet+0x1ce8/0x4d84) from [] (hci_rx_task+0x1d0/0x2d0) [] (hci_rx_task+0x1d0/0x2d0) from [] (tasklet_action+0x138/0x1e4) [] (tasklet_action+0x138/0x1e4) from [] (__do_softirq+0xcc/0x274) [] (__do_softirq+0xcc/0x274) from [] (do_softirq+0x60/0x6c) [] (do_softirq+0x60/0x6c) from [] (local_bh_enable_ip+0xc8/0xd4) [] (local_bh_enable_ip+0xc8/0xd4) from [] (_raw_spin_unlock_bh+0x48/0x4c) [] (_raw_spin_unlock_bh+0x48/0x4c) from [] (data_from_chip+0xf4/0xaec) [] (data_from_chip+0xf4/0xaec) from [] (send_skb_to_core+0x40/0x178) [] (send_skb_to_core+0x40/0x178) from [] (cg2900_hu_receive+0x15c/0x2d0) [] (cg2900_hu_receive+0x15c/0x2d0) from [] (hci_uart_tty_receive+0x74/0xa0) [] (hci_uart_tty_receive+0x74/0xa0) from [] (flush_to_ldisc+0x188/0x198) [] (flush_to_ldisc+0x188/0x198) from [] (process_one_work+0x144/0x4b8) [] (process_one_work+0x144/0x4b8) from [] (worker_thread+0x198/0x468) [] (worker_thread+0x198/0x468) from [] (kthread+0x98/0xa0) [] (kthread+0x98/0xa0) from [] (kernel_thread_exit+0x0/0x8) Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index d5eee20..e2e3eca 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -211,6 +211,7 @@ struct rfcomm_dlc { #define RFCOMM_AUTH_ACCEPT 6 #define RFCOMM_AUTH_REJECT 7 #define RFCOMM_DEFER_SETUP 8 +#define RFCOMM_ENC_DROP 9 /* Scheduling flags and events */ #define RFCOMM_SCHED_WAKEUP 31 diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5ba3f6d..71ef258 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1802,6 +1802,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) continue; } + if (test_bit(RFCOMM_ENC_DROP, &d->flags)) { + __rfcomm_dlc_close(d, ECONNREFUSED); + continue; + } + if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) { rfcomm_dlc_clear_timer(d); if (d->out) { @@ -2074,7 +2079,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) { rfcomm_dlc_clear_timer(d); if (status || encrypt == 0x00) { - __rfcomm_dlc_close(d, ECONNREFUSED); + set_bit(RFCOMM_ENC_DROP, &d->flags); continue; } } @@ -2085,7 +2090,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); continue; } else if (d->sec_level == BT_SECURITY_HIGH) { - __rfcomm_dlc_close(d, ECONNREFUSED); + set_bit(RFCOMM_ENC_DROP, &d->flags); continue; } } -- cgit v0.10.2 From e1b6eb3ccb0c2a34302a9fd87dd15d7b86337f23 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 17 Oct 2011 23:05:49 +0200 Subject: Bluetooth: Increase HCI reset timeout in hci_dev_do_close I've noticed that my CSR usb dongle was not working if it was plugged in when PC was booting. It looks like I get two HCI reset command complete events (see hcidump logs below). The root cause is reset called from off_timer. Timeout for this reset to complete is set to 250ms and my bt dongle requires more time for replying with command complete event. After that, chip seems to reply with reset command complete event for next non-reset command. Attached patch increase mentioned timeout to HCI_INIT_TIMEOUT, this value is already used for timeouting hci_reset_req in hci_dev_reset(). This might also be related to BT not working after suspend that was reported here some time ago. Hcidump log: 2011-09-12 23:13:27.379465 < HCI Command: Reset (0x03|0x0003) plen 0 2011-09-12 23:13:27.380797 > HCI Event: Command Complete (0x0e) plen 4 Reset (0x03|0x0003) ncmd 1 status 0x00 2011-09-12 23:13:27.380859 < HCI Command: Read Local Supported Features (0x04|0x000 3) plen 0 2011-09-12 23:13:27.760789 > HCI Event: Command Complete (0x0e) plen 4 Reset (0x03|0x0003) ncmd 1 status 0x00 2011-09-12 23:13:27.760831 < HCI Command: Read Local Version Information (0x04|0x00 01) plen 0 2011-09-12 23:13:27.764780 > HCI Event: Command Complete (0x0e) plen 12 Read Local Version Information (0x04|0x0001) ncmd 1 status 0x00 HCI Version: 1.1 (0x1) HCI Revision: 0x36f LMP Version: 1.1 (0x1) LMP Subversion: 0x36f Manufacturer: Cambridge Silicon Radio (10) Signed-off-by: Szymon Janc Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 56943ad..44fb4a7e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -613,7 +613,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) if (!test_bit(HCI_RAW, &hdev->flags)) { set_bit(HCI_INIT, &hdev->flags); __hci_request(hdev, hci_reset_req, 0, - msecs_to_jiffies(250)); + msecs_to_jiffies(HCI_INIT_TIMEOUT)); clear_bit(HCI_INIT, &hdev->flags); } -- cgit v0.10.2 From dafbde395ed560ddc3695df40f61d91c47433228 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 24 Oct 2011 22:36:26 +0200 Subject: Bluetooth: Set HCI_MGMT flag only in read_controller_info The HCI_MGMT flag should only be set when user space requests the full controller information. This way we avoid potential issues with setting change events ariving before the actual read_controller_info command finishes. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 53e109e..99251d1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -147,8 +147,6 @@ static int read_index_list(struct sock *sk) hci_del_off_timer(d); - set_bit(HCI_MGMT, &d->flags); - if (test_bit(HCI_SETUP, &d->flags)) continue; -- cgit v0.10.2 From 0ba22bb258341783939ed07bf7e7a9d92f3b0edf Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 25 Oct 2011 12:09:52 +0200 Subject: Bluetooth: ath3k: Use GFP_KERNEL instead of GFP_ATOMIC We are allowed to sleep here so no need to use GFP_ATOMIC. The caller (ath3k_probe) calls request_firmware() which definitely sleeps. Hence, we should avoid using GFP_ATOMIC. Signed-off-by: David Herrmann Signed-off-by: Gustavo F. Padovan diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index db7cb81..106beb1 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -105,7 +105,7 @@ static int ath3k_load_firmware(struct usb_device *udev, pipe = usb_sndctrlpipe(udev, 0); - send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); + send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); if (!send_buf) { BT_ERR("Can't allocate memory chunk for firmware"); return -ENOMEM; @@ -176,7 +176,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, count = firmware->size; - send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); + send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); if (!send_buf) { BT_ERR("Can't allocate memory chunk for firmware"); return -ENOMEM; -- cgit v0.10.2 From fc501ad7a10a356819505b1e526079d47fdebc2c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 26 Oct 2011 11:13:13 +0200 Subject: Bluetooth: bcm203x: Fix race condition on disconnect When disconnecting a bcm203x device we kill and destroy the usb-urb, however, there might still be a pending work-structure which resubmits the now invalid urb. To avoid this race condition, we simply set a shutdown-flag and synchronously kill the worker first. This also adds a comment to all schedule_work()s, as it is really not clear that they are used as replacement for short timers (which can be seen in the git history). Signed-off-by: David Herrmann Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 8b1b643..ec743c2 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -65,6 +66,7 @@ struct bcm203x_data { unsigned long state; struct work_struct work; + atomic_t shutdown; struct urb *urb; unsigned char *buffer; @@ -97,6 +99,7 @@ static void bcm203x_complete(struct urb *urb) data->state = BCM203X_SELECT_MEMORY; + /* use workqueue to have a small delay */ schedule_work(&data->work); break; @@ -155,6 +158,9 @@ static void bcm203x_work(struct work_struct *work) struct bcm203x_data *data = container_of(work, struct bcm203x_data, work); + if (atomic_read(&data->shutdown)) + return; + if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); } @@ -243,6 +249,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id usb_set_intfdata(intf, data); + /* use workqueue to have a small delay */ schedule_work(&data->work); return 0; @@ -254,6 +261,9 @@ static void bcm203x_disconnect(struct usb_interface *intf) BT_DBG("intf %p", intf); + atomic_inc(&data->shutdown); + cancel_work_sync(&data->work); + usb_kill_urb(data->urb); usb_set_intfdata(intf, NULL); -- cgit v0.10.2 From b91a4e3e3a16085623d47f03b338d9b74954ac67 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 25 Oct 2011 21:13:36 +0200 Subject: Bluetooth: bcm203x: Use GFP_KERNEL in workqueue A workqueue is allowed to sleep so we can safely use GFP_KERNEL instead of GFP_ATOMIC. This is still legacy code when the driver used timer BHs and not a worqueue. Signed-off-by: David Herrmann Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index ec743c2..54952ab 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -161,7 +161,7 @@ static void bcm203x_work(struct work_struct *work) if (atomic_read(&data->shutdown)) return; - if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) + if (usb_submit_urb(data->urb, GFP_KERNEL) < 0) BT_ERR("Can't submit URB"); } -- cgit v0.10.2 From 6b441fab28ea1cbbf3da75dcd1e7438e6cba704c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 26 Oct 2011 11:22:46 +0200 Subject: Bluetooth: bfusb: Fix error path on firmware load When loading the usb-configuration we do not signal the end of configuration on memory allocation error. This patch moves the memory allocation to the top so every error path uses "goto error" now to correctly send the usb-ctrl message when detecting some error. This also replaces GFP_ATOMIC with GFP_KERNEL as we are allowed to sleep here. Signed-off-by: David Herrmann Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 005919a..61b5914 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -568,22 +568,23 @@ static int bfusb_load_firmware(struct bfusb_data *data, BT_INFO("BlueFRITZ! USB loading firmware"); + buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL); + if (!buf) { + BT_ERR("Can't allocate memory chunk for firmware"); + return -ENOMEM; + } + pipe = usb_sndctrlpipe(data->udev, 0); if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) { BT_ERR("Can't change to loading configuration"); + kfree(buf); return -EBUSY; } data->udev->toggle[0] = data->udev->toggle[1] = 0; - buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC); - if (!buf) { - BT_ERR("Can't allocate memory chunk for firmware"); - return -ENOMEM; - } - pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); while (count) { -- cgit v0.10.2 From cda4ee3f2e6907e89baf7a12e02e02fa208c0625 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 14 Oct 2011 12:54:47 -0700 Subject: iwlagn: fix the race in the unmapping of the HCMD As Stanislaw pointed out, my patch iwlagn: fix a race in the unmapping of the TFDs solved only part of the problem. The race still exists for TFDs of the host commands. Fix that too. Reported-by: Stanislaw Gruszka Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 8e8c75c..da34110 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -407,6 +407,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) struct iwl_queue *q = &txq->q; enum dma_data_direction dma_dir; unsigned long flags; + spinlock_t *lock; if (!q->n_bd) return; @@ -414,19 +415,22 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) /* In the command queue, all the TBs are mapped as BIDI * so unmap them as such. */ - if (txq_id == trans->shrd->cmd_queue) + if (txq_id == trans->shrd->cmd_queue) { dma_dir = DMA_BIDIRECTIONAL; - else + lock = &trans->hcmd_lock; + } else { dma_dir = DMA_TO_DEVICE; + lock = &trans->shrd->sta_lock; + } - spin_lock_irqsave(&trans->shrd->sta_lock, flags); + spin_lock_irqsave(lock, flags); while (q->write_ptr != q->read_ptr) { /* The read_ptr needs to bound by q->n_window */ iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr), dma_dir); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + spin_unlock_irqrestore(lock, flags); } /** -- cgit v0.10.2 From 52d6d4ef5e6d1517688e27c11c01ab303ec681dd Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 20 Oct 2011 14:22:43 +0530 Subject: ath9k_hw: Fix regression of register offset for AR9003 chips My recent commits (3782c69d, 324c74a) introduced regression for register offset selection that based on the macversion. Not using parentheses in proper manner for ternary operator leads to select wrong offset for the registers. This issue was observed with AR9462 chip that immediate disconnect after the association with the following message ieee80211 phy3: wlan0: Failed to send nullfunc to AP 00:23:69:12:ea:47 after 500ms, disconnecting. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2f4023e..70e0103 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -572,14 +572,14 @@ #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) -#define AR_PHY_TX_IQCAL_CONTROL_0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3c4 : 0x444) -#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3c8 : 0x448) -#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3c4 : 0x440) -#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ - 0x3f0 : 0x48c) +#define AR_PHY_TX_IQCAL_CONTROL_0 (AR_SM_BASE + (AR_SREV_9485(ah) ? \ + 0x3c4 : 0x444)) +#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + (AR_SREV_9485(ah) ? \ + 0x3c8 : 0x448)) +#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + (AR_SREV_9485(ah) ? \ + 0x3c4 : 0x440)) +#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + (AR_SREV_9485(ah) ? \ + 0x3f0 : 0x48c)) #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ (AR_SREV_9485(ah) ? \ 0x3d0 : 0x450) + ((_i) << 2)) @@ -931,10 +931,10 @@ #define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0) #define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4) -#define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + (i) ? \ - AR_SM1_BASE : AR_SM_BASE) -#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + (i) ? \ - AR_SM1_BASE : AR_SM_BASE) +#define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + ((i) ? \ + AR_SM1_BASE : AR_SM_BASE)) +#define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + ((i) ? \ + AR_SM1_BASE : AR_SM_BASE)) /* * Channel 2 Register Map */ -- cgit v0.10.2 From 91ae4d02913808fc4056168766185d1a3bd63f65 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 20 Oct 2011 14:29:38 +0530 Subject: ath9k_hw: Fix radio retention for AR9462 IQ calibration during fast channel change sometimes failed with RTT. And also restoring invalid radio retention readings during init cal could cause failure to set the channel properly. This patch counts the valid rtt history readings and clears rtt mask. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 16851cb..a4cd161 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -908,12 +908,15 @@ static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) int i; bool restore; - if (!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT) || !ah->caldata) + if (!ah->caldata) return false; hist = &ah->caldata->rtt_hist; + if (!hist->num_readings) + return false; + ar9003_hw_rtt_enable(ah); - ar9003_hw_rtt_set_mask(ah, 0x10); + ar9003_hw_rtt_set_mask(ah, 0x00); for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (!(ah->rxchainmask & (1 << i))) continue; @@ -1070,6 +1073,7 @@ skip_tx_iqcal: if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) { u32 *table; + hist->num_readings++; for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (!(ah->rxchainmask & (1 << i))) continue; -- cgit v0.10.2 From eaa7af2ae582c9a8c51b374c48d5970b748a5ce2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 20 Oct 2011 19:05:49 +0200 Subject: mac80211: fix remain_off_channel regression The offchannel code is currently broken - we should remain_off_channel if the work was started, and the work's channel and channel_type are the same as local->tmp_channel and local->tmp_channel_type. However, if wk->chan_type and local->tmp_channel_type coexist (e.g. have the same channel type), we won't remain_off_channel. This behavior was introduced by commit da2fd1f ("mac80211: Allow work items to use existing channel type.") Tested-by: Ben Greear Signed-off-by: Eliad Peller Cc: stable@kernel.org # 2.6.39+ Signed-off-by: John W. Linville diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 94472eb..bf5be22 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -1084,8 +1084,8 @@ static void ieee80211_work_work(struct work_struct *work) continue; if (wk->chan != local->tmp_channel) continue; - if (ieee80211_work_ct_coexists(wk->chan_type, - local->tmp_channel_type)) + if (!ieee80211_work_ct_coexists(wk->chan_type, + local->tmp_channel_type)) continue; remain_off_channel = true; } -- cgit v0.10.2 From 6911bf0453e0d6ea8eb694a4ce67a68d071c538e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 20 Oct 2011 19:05:50 +0200 Subject: mac80211: config hw when going back on-channel When going back on-channel, we should reconfigure the hw iff the hardware is not already configured to the operational channel. Signed-off-by: Eliad Peller Cc: stable@kernel.org # 2.6.39+ Signed-off-by: John W. Linville diff --git a/net/mac80211/work.c b/net/mac80211/work.c index bf5be22..6c53b6d 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -1091,7 +1091,6 @@ static void ieee80211_work_work(struct work_struct *work) } if (!remain_off_channel && local->tmp_channel) { - bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); local->tmp_channel = NULL; /* If tmp_channel wasn't operating channel, then * we need to go back on-channel. @@ -1101,7 +1100,7 @@ static void ieee80211_work_work(struct work_struct *work) * we still need to do a hardware config. Currently, * we cannot be here while scanning, however. */ - if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) + if (!ieee80211_cfg_on_oper_channel(local)) ieee80211_hw_config(local, 0); /* At the least, we need to disable offchannel_ps, -- cgit v0.10.2 From fd26981cf53ee91951a92fae53416e4ce639164c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 21 Oct 2011 12:53:51 +0530 Subject: ath9k_hw: Fix regression of register offset of AR9330/AR9340 The commit ce407afc10 introduced regression for AR9330/AR9340 register offsets. Some of the register offsets are common for AR9330/AR9340/AR9485 except AR9380. Fix that. Cc: stable@kernel.org [3.1.0+] Cc: Senthil Balasubramanian Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 70e0103..4114fe7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -651,7 +651,7 @@ #define AR_SWITCH_TABLE_ALL_S (0) #define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\ - (AR_SREV_9485(ah) ? 0x1628c : 0x16294)) + (AR_SREV_9462(ah) ? 0x16294 : 0x1628c)) #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 @@ -668,12 +668,12 @@ #define AR_PHY_65NM_CH2_RXTX2 0x16904 #define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \ - (AR_SREV_9485(ah) ? 0x16284 : 0x16290)) + (AR_SREV_9462(ah) ? 0x16290 : 0x16284)) #define AR_CH0_TOP2_XPABIASLVL 0xf000 #define AR_CH0_TOP2_XPABIASLVL_S 12 #define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \ - (AR_SREV_9485(ah) ? 0x16290 : 0x16298)) + (AR_SREV_9462(ah) ? 0x16298 : 0x16290)) #define AR_CH0_XTAL_CAPINDAC 0x7f000000 #define AR_CH0_XTAL_CAPINDAC_S 24 #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 @@ -908,8 +908,8 @@ #define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208) #define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c) #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) -#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9300(ah) ? \ - 0x240 : 0x280)) +#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \ + 0x280 : 0x240)) #define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240) #define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff #define AR_PHY_TPC_19_B1_ALPHA_THERM_S 0 -- cgit v0.10.2 From 94d55d62bd757611f07a9122e5e07ce929b8d38d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 21 Oct 2011 18:38:56 +0200 Subject: carl9170: fix AMPDU TX_CTL_REQ_TX_STATUS handling Previously the driver did not care if TX_CTL_REQ_TX_STATUS was set on aggregated frames or not and it would silently drop successfully sent frames if possible [much like: "no news is good news!"]. But, TX_CTL_REQ_TX_STATUS was invented for a reason and no tx status report should ever be dropped if it is set. Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index d209469..59472e1 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -296,7 +296,8 @@ static void carl9170_tx_release(struct kref *ref) super = (void *)skb->data; txinfo->status.ampdu_len = super->s.rix; txinfo->status.ampdu_ack_len = super->s.cnt; - } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) { + } else if ((txinfo->flags & IEEE80211_TX_STAT_ACK) && + !(txinfo->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { /* * drop redundant tx_status reports: * @@ -308,15 +309,17 @@ static void carl9170_tx_release(struct kref *ref) * * 3. minstrel_ht is picky, it only accepts * reports of frames with the TX_STATUS_AMPDU flag. + * + * 4. mac80211 is not particularly interested in + * feedback either [CTL_REQ_TX_STATUS not set] */ dev_kfree_skb_any(skb); return; } else { /* - * Frame has failed, but we want to keep it in - * case it was lost due to a power-state - * transition. + * Either the frame transmission has failed or + * mac80211 requested tx status. */ } } -- cgit v0.10.2 From e3a4cc2f073739c9c9c2e97efc774703061f034a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Oct 2011 22:36:04 +0300 Subject: mac80211: Fix TDLS support validation in add_station handler We need to verify whether the command is successful before allocating the station entry to avoid extra processing. This also fixes a memory leak on the error path. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ebd7fb1..d06c65f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -832,6 +832,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, if (is_multicast_ether_addr(mac)) return -EINVAL; + /* Only TDLS-supporting stations can add TDLS peers */ + if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && + !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && + sdata->vif.type == NL80211_IFTYPE_STATION)) + return -ENOTSUPP; + sta = sta_info_alloc(sdata, mac, GFP_KERNEL); if (!sta) return -ENOMEM; @@ -841,12 +847,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, sta_apply_parameters(local, sta, params); - /* Only TDLS-supporting stations can add TDLS peers */ - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && - !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && - sdata->vif.type == NL80211_IFTYPE_STATION)) - return -ENOTSUPP; - rate_control_rate_init(sta); layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || -- cgit v0.10.2 From 98fb2cc115b4ef1ea0a2d87a170c183bd395dd6c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 24 Oct 2011 18:13:40 +0530 Subject: ath9k_hw: Update AR9485 initvals to fix system hang issue This patch fixes system hang when resuming from S3 state and lower rate sens failure issue. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 611ea6c..d16d029 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -521,7 +521,7 @@ static const u32 ar9485_1_1_radio_postamble[][2] = { {0x000160ac, 0x24611800}, {0x000160b0, 0x03284f3e}, {0x0001610c, 0x00170000}, - {0x00016140, 0x10804008}, + {0x00016140, 0x50804008}, }; static const u32 ar9485_1_1_mac_postamble[][5] = { @@ -603,7 +603,7 @@ static const u32 ar9485_1_1_radio_core[][2] = { static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = { /* Addr allmodes */ - {0x00018c00, 0x10052e5e}, + {0x00018c00, 0x18052e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; @@ -776,7 +776,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = { /* Addr allmodes */ - {0x00018c00, 0x10013e5e}, + {0x00018c00, 0x18013e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; @@ -882,7 +882,7 @@ static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = { static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { /* Addr allmodes */ - {0x00018c00, 0x10012e5e}, + {0x00018c00, 0x18012e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; @@ -1021,7 +1021,7 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = { static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = { /* Addr allmodes */ - {0x00018c00, 0x10053e5e}, + {0x00018c00, 0x18053e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; -- cgit v0.10.2 From 93348928f2c980718434b1bc42f9d7638d665db4 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 25 Oct 2011 16:47:36 +0530 Subject: ath9k_hw: Fix noise floor calibration timeout on fast channel change During the fast channel change noise floor values are being loaded twice at init_cal and after channel_change. The commit "ath9k_hw: Improve fast channel change for AR9003 chips" overlooked it that caused failure to load nf while doing bgscan. This patch performs noise floor calibration after the fast and full reset. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index e0ab065..88279e3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -868,10 +868,6 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) /* Do PA Calibration */ ar9002_hw_pa_cal(ah, true); - /* Do NF Calibration after DC offset and other calibrations */ - ath9k_hw_loadnf(ah, chan); - ath9k_hw_start_nfcal(ah, true); - if (ah->caldata) ah->caldata->nfcal_pending = true; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index a4cd161..12a730d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1085,9 +1085,6 @@ skip_tx_iqcal: ar9003_hw_rtt_disable(ah); } - ath9k_hw_loadnf(ah, chan); - ath9k_hw_start_nfcal(ah, true); - /* Initialize list pointers */ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ah->supp_cals = IQ_MISMATCH_CAL; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f16d203..b479160 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1724,6 +1724,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_init_cal(ah, chan)) return -EIO; + ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + ENABLE_REGWRITE_BUFFER(ah); ath9k_hw_restore_chainmask(ah); -- cgit v0.10.2 From 3209e061ad04465b3999091f315049c95ac6cbcb Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Wed, 26 Oct 2011 10:19:26 -0700 Subject: libertas: ensure we clean up a scan request properly Commit 2e30168b ("libertas: terminate scan when stopping interface") adds cleanup code to lbs_eth_stop to call cfg80211_scan_done if there's an outstanding cfg80211_scan_request. However, it assumes that the scan request was allocated via the cfg80211 stack. Libertas has its own internal allocation method, kept track of with priv->internal_scan. This doesn't set scan_req->wiphy, amongst other things, which results in hitting a BUG() when we call cfg80211_scan_done on the request. This provides a function to take care of the low-level scan_req cleanup details. We simply call that to deal with finishing up scan requests. The bug we were hitting was: [ 964.321495] kernel BUG at net/wireless/core.h:87! [ 964.329970] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 964.341963] pgd = dcf80000 ... [ 964.849998] 9fe0: 00000000 beb417b8 4018e280 401e822c 60000010 00000004 00000000 00000000 [ 964.865007] [] (__bug+0x1c/0x28) from [] (cfg80211_scan_done+0x54/0x6c) [ 964.895324] [] (cfg80211_scan_done+0x54/0x6c) from [] (lbs_eth_stop+0x10c/0x188 [libertas]) [ 964.895324] [] (lbs_eth_stop+0x10c/0x188 [libertas]) from [] (__dev_close_many+0x94/0xc4) [ 964.918995] [] (__dev_close_many+0x94/0xc4) from [] (dev_close_many+0x78/0xe0) Signed-off-by: Andres Salomon Acked-by: Dan Williams Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index ff63782..4fcd653 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -728,15 +728,9 @@ static void lbs_scan_worker(struct work_struct *work) le16_to_cpu(scan_cmd->hdr.size), lbs_ret_scan, 0); - if (priv->scan_channel >= priv->scan_req->n_channels) { + if (priv->scan_channel >= priv->scan_req->n_channels) /* Mark scan done */ - if (priv->internal_scan) - kfree(priv->scan_req); - else - cfg80211_scan_done(priv->scan_req, false); - - priv->scan_req = NULL; - } + lbs_scan_done(priv); /* Restart network */ if (carrier) @@ -774,6 +768,21 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal, lbs_deb_leave(LBS_DEB_CFG80211); } +/* + * Clean up priv->scan_req. Should be used to handle the allocation details. + */ +void lbs_scan_done(struct lbs_private *priv) +{ + WARN_ON(!priv->scan_req); + + if (priv->internal_scan) + kfree(priv->scan_req); + else + cfg80211_scan_done(priv->scan_req, false); + + priv->scan_req = NULL; +} + static int lbs_cfg_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h index a02ee15..558168c 100644 --- a/drivers/net/wireless/libertas/cfg.h +++ b/drivers/net/wireless/libertas/cfg.h @@ -16,6 +16,7 @@ int lbs_reg_notifier(struct wiphy *wiphy, void lbs_send_disconnect_notification(struct lbs_private *priv); void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); +void lbs_scan_done(struct lbs_private *priv); void lbs_scan_deinit(struct lbs_private *priv); int lbs_disconnect(struct lbs_private *priv, u16 reason); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index b03779b..39a6a7a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -255,10 +255,8 @@ static int lbs_eth_stop(struct net_device *dev) lbs_update_mcast(priv); cancel_delayed_work_sync(&priv->scan_work); - if (priv->scan_req) { - cfg80211_scan_done(priv->scan_req, false); - priv->scan_req = NULL; - } + if (priv->scan_req) + lbs_scan_done(priv); netif_carrier_off(priv->dev); -- cgit v0.10.2 From 8a39ef8ba0fa0410d71db8e981e887fe4fdeca88 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 27 Oct 2011 17:19:39 -0700 Subject: iwlwifi: allow pci_enable_msi fail Continue the init process even fail to enable msi out_iounmap is no longer used, remove it Reported-by: werner Tested-by: werner Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 3b6cc66..19cc6a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -445,10 +445,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); err = pci_enable_msi(pdev); - if (err) { - dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed"); - goto out_iounmap; - } + if (err) + dev_printk(KERN_ERR, &pdev->dev, + "pci_enable_msi failed(0X%x)", err); /* TODO: Move this away, not needed if not MSI */ /* enable rfkill interrupt: hw bug w/a */ @@ -469,7 +468,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_disable_msi: pci_disable_msi(pdev); -out_iounmap: pci_iounmap(pdev, pci_bus->hw_base); out_pci_release_regions: pci_set_drvdata(pdev, NULL); -- cgit v0.10.2 From 05cb91085760ca378f28fc274fbf77fc4fd9886c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 28 Oct 2011 11:59:47 +0200 Subject: mac80211: disable powersave for broken APs Only AID values 1-2007 are valid, but some APs have been found to send random bogus values, in the reported case an AP that was sending the AID field value 0xffff, an AID of 0x3fff (16383). There isn't much we can do but disable powersave since there's no way it can work properly in this case. Cc: stable@vger.kernel.org Reported-by: Bill C Riemers Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4c3d1f5..ea10a51 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -389,6 +389,7 @@ struct ieee80211_if_managed { unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ + bool broken_ap; /* AP is broken -- turn off powersave */ enum ieee80211_smps_mode req_smps, /* requested smps mode */ ap_smps, /* smps mode AP thinks we're in */ driver_smps_mode; /* smps mode request */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ba2da11..17258fe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -637,6 +637,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) if (!mgd->powersave) return false; + if (mgd->broken_ap) + return false; + if (!mgd->associated) return false; @@ -1489,10 +1492,21 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", sdata->name, aid); + printk(KERN_DEBUG + "%s: invalid AID value 0x%x; bits 15:14 not set\n", + sdata->name, aid); aid &= ~(BIT(15) | BIT(14)); + ifmgd->broken_ap = false; + + if (aid == 0 || aid > IEEE80211_MAX_AID) { + printk(KERN_DEBUG + "%s: invalid AID value %d (out of range), turn off PS\n", + sdata->name, aid); + aid = 0; + ifmgd->broken_ap = true; + } + pos = mgmt->u.assoc_resp.variable; ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); -- cgit v0.10.2 From addc98519207fb8ca0609da720469e415f784d0c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 28 Oct 2011 12:17:49 -0500 Subject: b43: Remove unneeded message The driver can spam the logs with "RX: Packet dropped" messages. These drops originate from 1. a correpted PLCP, 2. decryption errors, and 3. packet size underruns. Condition #3 logs a separate message, thus no dropped message is needed. Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index c73e860..58ea0e5 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -827,7 +827,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) #endif return; drop: - b43dbg(dev->wl, "RX: Packet dropped\n"); dev_kfree_skb_any(skb); } -- cgit v0.10.2 From f956c34e2a665a1c457d0af7db7604b22f5acb19 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 29 Oct 2011 23:15:15 -0700 Subject: iwlwifi: don't perform "echo test" when cmd queue stuck Perform "echo test" when cmd queue stuck detected, somethime it will cause calltrace. I am not sure how to fix it yet, just remove the action now until find a better way to handle it. Reported-by: Reinette Chatre Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b247a56..001fdf1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1755,16 +1755,6 @@ static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq) { if (iwl_trans_check_stuck_queue(trans(priv), txq)) { int ret; - if (txq == priv->shrd->cmd_queue) { - /* - * validate command queue still working - * by sending "ECHO" command - */ - if (!iwl_cmd_echo_test(priv)) - return 0; - else - IWL_DEBUG_HC(priv, "echo testing fail\n"); - } ret = iwl_force_reset(priv, IWL_FW_RESET, false); return (ret == -EAGAIN) ? 0 : 1; } -- cgit v0.10.2 From 54d5026e7c173edae8a27c293c286f1783d21ae8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Nov 2011 18:07:43 +0100 Subject: mac80211: warn only once about not finding a rate The warning really shouldn't happen, but until we find the reason why it does don't spew it all the time, just once is enough to know we've hit it. Reported-by: Linus Torvalds Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/include/net/mac80211.h b/include/net/mac80211.h index dc1123a..72eddd1 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3567,8 +3567,9 @@ rate_lowest_index(struct ieee80211_supported_band *sband, return i; /* warn when we cannot find a rate. */ - WARN_ON(1); + WARN_ON_ONCE(1); + /* and return 0 (the lowest index) */ return 0; } -- cgit v0.10.2 From 78f94dc7b10d98cf4cf8498d98581500d910c6b7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:14:58 +0000 Subject: tg3: Fix APE mutex init and use APE mutex register blocks are shared by all ports of multiport devices. For some mutexing purposes, each function is assigned their own register. For other cases, each function is assigned its own request and grant bits of a single register. For the latter cases, the tg3 driver is incorrectly allowing each function to use the same set of grant / request bits. This patch fixes the code so that each function uses the appropriate bitset. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 161cbbb..3590163 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -628,19 +628,23 @@ static void tg3_ape_lock_init(struct tg3 *tp) regbase = TG3_APE_PER_LOCK_GRANT; /* Make sure the driver hasn't any stale locks. */ - for (i = 0; i < 8; i++) { - if (i == TG3_APE_LOCK_GPIO) - continue; - tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER); + for (i = TG3_APE_LOCK_PHY0; i <= TG3_APE_LOCK_GPIO; i++) { + switch (i) { + case TG3_APE_LOCK_PHY0: + case TG3_APE_LOCK_PHY1: + case TG3_APE_LOCK_PHY2: + case TG3_APE_LOCK_PHY3: + bit = APE_LOCK_GRANT_DRIVER; + break; + default: + if (!tp->pci_fn) + bit = APE_LOCK_GRANT_DRIVER; + else + bit = 1 << tp->pci_fn; + } + tg3_ape_write32(tp, regbase + 4 * i, bit); } - /* Clear the correct bit of the GPIO lock too. */ - if (!tp->pci_fn) - bit = APE_LOCK_GRANT_DRIVER; - else - bit = 1 << tp->pci_fn; - - tg3_ape_write32(tp, regbase + 4 * TG3_APE_LOCK_GPIO, bit); } static int tg3_ape_lock(struct tg3 *tp, int locknum) @@ -658,6 +662,10 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) return 0; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: + if (!tp->pci_fn) + bit = APE_LOCK_REQ_DRIVER; + else + bit = 1 << tp->pci_fn; break; default: return -EINVAL; @@ -673,11 +681,6 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) off = 4 * locknum; - if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn) - bit = APE_LOCK_REQ_DRIVER; - else - bit = 1 << tp->pci_fn; - tg3_ape_write32(tp, req + off, bit); /* Wait for up to 1 millisecond to acquire lock. */ @@ -710,6 +713,10 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) return; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: + if (!tp->pci_fn) + bit = APE_LOCK_GRANT_DRIVER; + else + bit = 1 << tp->pci_fn; break; default: return; @@ -720,11 +727,6 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) else gnt = TG3_APE_PER_LOCK_GRANT; - if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn) - bit = APE_LOCK_GRANT_DRIVER; - else - bit = 1 << tp->pci_fn; - tg3_ape_write32(tp, gnt + 4 * locknum, bit); } diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index f32f288..03fab8c 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2344,9 +2344,13 @@ #define APE_PER_LOCK_GRANT_DRIVER 0x00001000 /* APE convenience enumerations. */ -#define TG3_APE_LOCK_GRC 1 -#define TG3_APE_LOCK_MEM 4 -#define TG3_APE_LOCK_GPIO 7 +#define TG3_APE_LOCK_PHY0 0 +#define TG3_APE_LOCK_GRC 1 +#define TG3_APE_LOCK_PHY1 2 +#define TG3_APE_LOCK_PHY2 3 +#define TG3_APE_LOCK_MEM 4 +#define TG3_APE_LOCK_PHY3 5 +#define TG3_APE_LOCK_GPIO 7 #define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 -- cgit v0.10.2 From b9e454826f22e17d1945bd282834c87aef8d0f95 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:14:59 +0000 Subject: tg3: Fix 4k tx bd segmentation code The new 4k tx bd segmentation code had a bug in the error cleanup path. If the driver did not map all the physical fragments, the abort path would wind up advancing the producer index beyond the point where the setup code stopped. This would ultimately turn into a tx recovery error where the driver would expect the skb pointer to be set when it isn't. This patch fixes the problem, and then makes the code a little easier to understand. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3590163..507b73b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6444,31 +6444,26 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget, hwbug = 1; if (tg3_flag(tp, 4K_FIFO_LIMIT)) { + u32 prvidx = *entry; u32 tmp_flag = flags & ~TXD_FLAG_END; - while (len > TG3_TX_BD_DMA_MAX) { + while (len > TG3_TX_BD_DMA_MAX && *budget) { u32 frag_len = TG3_TX_BD_DMA_MAX; len -= TG3_TX_BD_DMA_MAX; - if (len) { - tnapi->tx_buffers[*entry].fragmented = true; - /* Avoid the 8byte DMA problem */ - if (len <= 8) { - len += TG3_TX_BD_DMA_MAX / 2; - frag_len = TG3_TX_BD_DMA_MAX / 2; - } - } else - tmp_flag = flags; - - if (*budget) { - tg3_tx_set_bd(&tnapi->tx_ring[*entry], map, - frag_len, tmp_flag, mss, vlan); - (*budget)--; - *entry = NEXT_TX(*entry); - } else { - hwbug = 1; - break; + /* Avoid the 8byte DMA problem */ + if (len <= 8) { + len += TG3_TX_BD_DMA_MAX / 2; + frag_len = TG3_TX_BD_DMA_MAX / 2; } + tnapi->tx_buffers[*entry].fragmented = true; + + tg3_tx_set_bd(&tnapi->tx_ring[*entry], map, + frag_len, tmp_flag, mss, vlan); + *budget -= 1; + prvidx = *entry; + *entry = NEXT_TX(*entry); + map += frag_len; } @@ -6476,10 +6471,11 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget, if (*budget) { tg3_tx_set_bd(&tnapi->tx_ring[*entry], map, len, flags, mss, vlan); - (*budget)--; + *budget -= 1; *entry = NEXT_TX(*entry); } else { hwbug = 1; + tnapi->tx_buffers[prvidx].fragmented = false; } } } else { @@ -6561,6 +6557,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, dev_kfree_skb(new_skb); ret = -1; } else { + u32 save_entry = *entry; + base_flags |= TXD_FLAG_END; tnapi->tx_buffers[*entry].skb = new_skb; @@ -6570,7 +6568,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, if (tg3_tx_frag_set(tnapi, entry, budget, new_addr, new_skb->len, base_flags, mss, vlan)) { - tg3_tx_skb_unmap(tnapi, *entry, 0); + tg3_tx_skb_unmap(tnapi, save_entry, 0); dev_kfree_skb(new_skb); ret = -1; } @@ -6786,11 +6784,14 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (dma_mapping_error(&tp->pdev->dev, mapping)) goto dma_error; - if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, + if (!budget || + tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags | ((i == last) ? TXD_FLAG_END : 0), - tmp_mss, vlan)) + tmp_mss, vlan)) { would_hit_hwbug = 1; + break; + } } } -- cgit v0.10.2 From ba1142e4fb291c7bf124d93596351dca8d226a0f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:00 +0000 Subject: tg3: Fix 4k skb error recovery path On the error recovery resource unwind path, it is possible for the driver to attempt to unmap a fragment that hadn't been mapped. This patch fixes the problem by correcting the "last" parameter supplied. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 507b73b..3a75179 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6507,7 +6507,7 @@ static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last) txb = &tnapi->tx_buffers[entry]; } - for (i = 0; i < last; i++) { + for (i = 0; i <= last; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; entry = NEXT_TX(entry); @@ -6568,7 +6568,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, if (tg3_tx_frag_set(tnapi, entry, budget, new_addr, new_skb->len, base_flags, mss, vlan)) { - tg3_tx_skb_unmap(tnapi, save_entry, 0); + tg3_tx_skb_unmap(tnapi, save_entry, -1); dev_kfree_skb(new_skb); ret = -1; } @@ -6758,11 +6758,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags | ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0), - mss, vlan)) + mss, vlan)) { would_hit_hwbug = 1; - /* Now loop through additional data fragments, and queue them. */ - if (skb_shinfo(skb)->nr_frags > 0) { + } else if (skb_shinfo(skb)->nr_frags > 0) { u32 tmp_mss = mss; if (!tg3_flag(tp, HW_TSO_1) && @@ -6831,7 +6830,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; dma_error: - tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i); + tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i); tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; drop: dev_kfree_skb(skb); @@ -7284,7 +7283,8 @@ static void tg3_free_rings(struct tg3 *tp) if (!skb) continue; - tg3_tx_skb_unmap(tnapi, i, skb_shinfo(skb)->nr_frags); + tg3_tx_skb_unmap(tnapi, i, + skb_shinfo(skb)->nr_frags - 1); dev_kfree_skb_any(skb); } @@ -11523,7 +11523,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) break; } - tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, 0); + tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, -1); dev_kfree_skb(skb); if (tx_idx != tnapi->tx_prod) -- cgit v0.10.2 From 5bc09186deba2a016b60aa3923fc0e42838ce877 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:01 +0000 Subject: tg3: Fix irq alloc error cleanup path This patch fixes a bug where the irq error cleanup path did not free all the resources it allocated. Signed-off-by: Matt Carlson Signed-off-by: Ben Li Signed-off-by: Akinobu Mita Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3a75179..0413e1e 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -9677,15 +9677,14 @@ static int tg3_open(struct net_device *dev) struct tg3_napi *tnapi = &tp->napi[i]; err = tg3_request_irq(tp, i); if (err) { - for (i--; i >= 0; i--) + for (i--; i >= 0; i--) { + tnapi = &tp->napi[i]; free_irq(tnapi->irq_vec, tnapi); - break; + } + goto err_out2; } } - if (err) - goto err_out2; - tg3_full_lock(tp, 0); err = tg3_init_hw(tp, 1); -- cgit v0.10.2 From 9dc5e342703948ea7b086d063c85c0e79dac8149 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:02 +0000 Subject: tg3: Obtain PCI function number from device This patch adds code to attempt to obtain the PCI function number from the device rather than accept the number handed by the kernel. In pass-through scenarios, the function number handed by the kernel may not reflect the true function of the device. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 0413e1e..6973d01 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14230,12 +14230,30 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) val = tr32(MEMARB_MODE); tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); - if (tg3_flag(tp, PCIX_MODE)) { - pci_read_config_dword(tp->pdev, - tp->pcix_cap + PCI_X_STATUS, &val); - tp->pci_fn = val & 0x7; - } else { - tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3; + tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || + tg3_flag(tp, 5780_CLASS)) { + if (tg3_flag(tp, PCIX_MODE)) { + pci_read_config_dword(tp->pdev, + tp->pcix_cap + PCI_X_STATUS, + &val); + tp->pci_fn = val & 0x7; + } + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { + tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val); + if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) == + NIC_SRAM_CPMUSTAT_SIG) { + tp->pci_fn = val & TG3_CPMU_STATUS_FMSK_5717; + tp->pci_fn = tp->pci_fn ? 1 : 0; + } + } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + tg3_read_mem(tp, NIC_SRAM_CPMU_STATUS, &val); + if ((val & NIC_SRAM_CPMUSTAT_SIG_MSK) == + NIC_SRAM_CPMUSTAT_SIG) { + tp->pci_fn = (val & TG3_CPMU_STATUS_FMSK_5719) >> + TG3_CPMU_STATUS_FSHFT_5719; + } } /* Get eeprom hw config before calling tg3_set_power_state(). diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 03fab8c..acfa265 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -1095,6 +1095,11 @@ #define TG3_CPMU_CLCK_ORIDE 0x00003624 #define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000 +#define TG3_CPMU_STATUS 0x0000362c +#define TG3_CPMU_STATUS_FMSK_5717 0x20000000 +#define TG3_CPMU_STATUS_FMSK_5719 0xc0000000 +#define TG3_CPMU_STATUS_FSHFT_5719 30 + #define TG3_CPMU_CLCK_STAT 0x00003630 #define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 #define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 @@ -2128,6 +2133,10 @@ #define NIC_SRAM_RGMII_EXT_IBND_RX_EN 0x00000008 #define NIC_SRAM_RGMII_EXT_IBND_TX_EN 0x00000010 +#define NIC_SRAM_CPMU_STATUS 0x00000e00 +#define NIC_SRAM_CPMUSTAT_SIG 0x0000362c +#define NIC_SRAM_CPMUSTAT_SIG_MSK 0x0000ffff + #define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000 #define NIC_SRAM_DMA_DESC_POOL_BASE 0x00002000 -- cgit v0.10.2 From db21997379906fe7657d360674e1106d80b020a4 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:03 +0000 Subject: tg3: Schedule at most one tg3_reset_task run It is possible for multiple threads in the tg3 driver to each attempt to schedule a run of tg3_reset_task(). The multiple tg3_reset_task executions could all wind up on the same queue (and execute serially) or wind up on the queues of another processor (which could execute in parallel). Either scenario is not what was truly desired. This patch adds a new flag, TG3_FLAG_RESET_TASK_PENDING, and uses it to determine whether or not to schedule another run of tg3_reset_task(). With the new flag comes two new functions to facilitate scheduling and descheduling of tg3_reset_task(). Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 6973d01..d4a85b7 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -5929,6 +5929,18 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) return work_done; } +static inline void tg3_reset_task_schedule(struct tg3 *tp) +{ + if (!test_and_set_bit(TG3_FLAG_RESET_TASK_PENDING, tp->tg3_flags)) + schedule_work(&tp->reset_task); +} + +static inline void tg3_reset_task_cancel(struct tg3 *tp) +{ + cancel_work_sync(&tp->reset_task); + tg3_flag_clear(tp, RESET_TASK_PENDING); +} + static int tg3_poll_msix(struct napi_struct *napi, int budget) { struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi); @@ -5969,7 +5981,7 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget) tx_recovery: /* work_done is guaranteed to be less than budget. */ napi_complete(napi); - schedule_work(&tp->reset_task); + tg3_reset_task_schedule(tp); return work_done; } @@ -6004,7 +6016,7 @@ static void tg3_process_error(struct tg3 *tp) tg3_dump_state(tp); tg3_flag_set(tp, ERROR_PROCESSED); - schedule_work(&tp->reset_task); + tg3_reset_task_schedule(tp); } static int tg3_poll(struct napi_struct *napi, int budget) @@ -6051,7 +6063,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) tx_recovery: /* work_done is guaranteed to be less than budget. */ napi_complete(napi); - schedule_work(&tp->reset_task); + tg3_reset_task_schedule(tp); return work_done; } @@ -6345,6 +6357,7 @@ static void tg3_reset_task(struct work_struct *work) tg3_full_lock(tp, 0); if (!netif_running(tp->dev)) { + tg3_flag_clear(tp, RESET_TASK_PENDING); tg3_full_unlock(tp); return; } @@ -6382,6 +6395,8 @@ out: if (!err) tg3_phy_start(tp); + + tg3_flag_clear(tp, RESET_TASK_PENDING); } static void tg3_tx_timeout(struct net_device *dev) @@ -6393,7 +6408,7 @@ static void tg3_tx_timeout(struct net_device *dev) tg3_dump_state(tp); } - schedule_work(&tp->reset_task); + tg3_reset_task_schedule(tp); } /* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */ @@ -9228,7 +9243,7 @@ static void tg3_timer(unsigned long __opaque) if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { tg3_flag_set(tp, RESTART_TIMER); spin_unlock(&tp->lock); - schedule_work(&tp->reset_task); + tg3_reset_task_schedule(tp); return; } } @@ -9785,7 +9800,7 @@ static int tg3_close(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); tg3_napi_disable(tp); - cancel_work_sync(&tp->reset_task); + tg3_reset_task_cancel(tp); netif_tx_stop_all_queues(dev); @@ -15685,7 +15700,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) if (tp->fw) release_firmware(tp->fw); - cancel_work_sync(&tp->reset_task); + tg3_reset_task_cancel(tp); if (tg3_flag(tp, USE_PHYLIB)) { tg3_phy_fini(tp); @@ -15719,7 +15734,7 @@ static int tg3_suspend(struct device *device) if (!netif_running(dev)) return 0; - flush_work_sync(&tp->reset_task); + tg3_reset_task_cancel(tp); tg3_phy_stop(tp); tg3_netif_stop(tp); @@ -15835,7 +15850,7 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_flag_clear(tp, RESTART_TIMER); /* Want to make sure that the reset task doesn't run */ - cancel_work_sync(&tp->reset_task); + tg3_reset_task_cancel(tp); tg3_flag_clear(tp, TX_RECOVERY_PENDING); tg3_flag_clear(tp, RESTART_TIMER); diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index acfa265..610fd84 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2922,6 +2922,7 @@ enum TG3_FLAGS { TG3_FLAG_APE_HAS_NCSI, TG3_FLAG_5717_PLUS, TG3_FLAG_4K_FIFO_LIMIT, + TG3_FLAG_RESET_TASK_PENDING, /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */ TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */ -- cgit v0.10.2 From 5b1906241905d9bd1abe920854b3d43c2b9c85e1 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:04 +0000 Subject: tg3: Eliminate timer race with reset_task During shutdown, it is impossible to reliably disable the timer and reset_task threads. Each thread can schedule the other, which leads to shutdown code that chases its tail. To fix the problem, this patch removes the ability of tg3_reset_task to schedule a new timer thread. To support this change, tg3_timer no longer terminates itself, but rather goes into a polling mode. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d4a85b7..cc7349f 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6352,7 +6352,6 @@ static void tg3_reset_task(struct work_struct *work) { struct tg3 *tp = container_of(work, struct tg3, reset_task); int err; - unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -6370,9 +6369,6 @@ static void tg3_reset_task(struct work_struct *work) tg3_full_lock(tp, 1); - restart_timer = tg3_flag(tp, RESTART_TIMER); - tg3_flag_clear(tp, RESTART_TIMER); - if (tg3_flag(tp, TX_RECOVERY_PENDING)) { tp->write32_tx_mbox = tg3_write32_tx_mbox; tp->write32_rx_mbox = tg3_write_flush_reg32; @@ -6387,9 +6383,6 @@ static void tg3_reset_task(struct work_struct *work) tg3_netif_start(tp); - if (restart_timer) - mod_timer(&tp->timer, jiffies + 1); - out: tg3_full_unlock(tp); @@ -9218,7 +9211,7 @@ static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; - if (tp->irq_sync) + if (tp->irq_sync || tg3_flag(tp, RESET_TASK_PENDING)) goto restart_timer; spin_lock(&tp->lock); @@ -9241,10 +9234,9 @@ static void tg3_timer(unsigned long __opaque) } if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - tg3_flag_set(tp, RESTART_TIMER); spin_unlock(&tp->lock); tg3_reset_task_schedule(tp); - return; + goto restart_timer; } } @@ -15847,12 +15839,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_netif_stop(tp); del_timer_sync(&tp->timer); - tg3_flag_clear(tp, RESTART_TIMER); /* Want to make sure that the reset task doesn't run */ tg3_reset_task_cancel(tp); tg3_flag_clear(tp, TX_RECOVERY_PENDING); - tg3_flag_clear(tp, RESTART_TIMER); netif_device_detach(netdev); diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 610fd84..94b4bd0 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -2879,7 +2879,6 @@ enum TG3_FLAGS { TG3_FLAG_JUMBO_CAPABLE, TG3_FLAG_CHIP_RESETTING, TG3_FLAG_INIT_COMPLETE, - TG3_FLAG_RESTART_TIMER, TG3_FLAG_TSO_BUG, TG3_FLAG_IS_5788, TG3_FLAG_MAX_RXPEND_64, -- cgit v0.10.2 From 5ae7fa06bb90421bc63f1f1e56ab241b49bc7b91 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 4 Nov 2011 09:15:05 +0000 Subject: tg3: Update version to 3.121 This patch updates the tg3 version to 3.121. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index cc7349f..bf40741 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 120 +#define TG3_MIN_NUM 121 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "August 18, 2011" +#define DRV_MODULE_RELDATE "November 2, 2011" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 -- cgit v0.10.2 From 729e72a10930ef765c11a5a35031ba47f18221c4 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 2 Nov 2011 12:11:53 +0000 Subject: macvlan: receive multicast with local address When implementing VRRP v2 using macvlan several problems were discovered. VRRP is weird in that all routers participating in a redundant group use the same virtual MAC address. Macvlan is a natural driver to use for this but it doesn't work. The problem is that packets with a macvlan device's source address are not received. The problem is actually a regression that date back almost 2 years now. The original problems started with: commit 618e1b7482f7a8a4c6c6e8ccbe140e4c331df4e9 Author: Arnd Bergmann Date: Thu Nov 26 06:07:10 2009 +0000 macvlan: implement bridge, VEPA and private mode This patches restores the original 2.6.32 behavior. Allowing multicast packets received with the VRRP source address to be received. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index a3ce3d4..7413497 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -192,6 +192,13 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) */ macvlan_broadcast(skb, port, src->dev, MACVLAN_MODE_VEPA); + else { + /* forward to original port. */ + vlan = src; + ret = macvlan_broadcast_one(skb, vlan, eth, 0); + goto out; + } + return RX_HANDLER_PASS; } -- cgit v0.10.2 From 433aee04a447fb2e769c4570f327d9c2a956117b Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 2 Nov 2011 00:30:52 +0000 Subject: i825xx:xscale:8390:freescale: Fix Kconfig dependancies i825xx and xscale are "sub" Kconfigs to NET_VENDOR_INTEL, so NET_VENDOR_INTEL should contain ALL the dependencies of the "sub" Kconfigs. Same with 8390 is a "sub" Kconfig to NET_VENDOR_NATSEMI, so NET_VENDOR_NATSEMI needs to contains ALL the dependencies. Freescale Kconfig only had fs_enet as a sub Kconfig, and already contained the needed dependencies, just cleaned up the dependencies. Reported-by: Geert Uytterhoeven Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 1cf6716..c520cfd 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -7,8 +7,7 @@ config NET_VENDOR_FREESCALE default y depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \ M523x || M527x || M5272 || M528x || M520x || M532x || \ - ARCH_MXC || ARCH_MXS || \ - (PPC_MPC52xx && PPC_BESTCOMM) + ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 61029dc..7621316 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -5,7 +5,11 @@ config NET_VENDOR_INTEL bool "Intel devices" default y - depends on PCI || PCI_MSI + depends on PCI || PCI_MSI || ISA || ISA_DMA_API || ARM || \ + ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \ + GSC || BVME6000 || MVME16x || ARCH_ENP2611 || \ + (ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR) || \ + EXPERIMENTAL ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/natsemi/Kconfig b/drivers/net/ethernet/natsemi/Kconfig index 4a6b9fd..eb836f7 100644 --- a/drivers/net/ethernet/natsemi/Kconfig +++ b/drivers/net/ethernet/natsemi/Kconfig @@ -5,7 +5,10 @@ config NET_VENDOR_NATSEMI bool "National Semi-conductor devices" default y - depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000 + depends on AMIGA_PCMCIA || ARM || EISA || EXPERIMENTAL || H8300 || \ + ISA || M32R || MAC || MACH_JAZZ || MACH_TX49XX || MCA || \ + MCA_LEGACY || MIPS || PCI || PCMCIA || SUPERH || \ + XTENSA_PLATFORM_XT2000 || ZORRO ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from -- cgit v0.10.2 From c30bc94758ae2a38a5eb31767c1985c0aae0950b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 Nov 2011 00:07:32 +0000 Subject: netlink: validate NLA_MSECS length L2TP for example uses NLA_MSECS like this: policy: [L2TP_ATTR_RECV_TIMEOUT] = { .type = NLA_MSECS, }, code: if (info->attrs[L2TP_ATTR_RECV_TIMEOUT]) cfg.reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]); As nla_get_msecs() is essentially nla_get_u64() plus the conversion to a HZ-based value, this will not properly reject attributes from userspace that aren't long enough and might overrun the message. Add NLA_MSECS to the attribute minlen array to check the size properly. Cc: Thomas Graf Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg Signed-off-by: David S. Miller diff --git a/lib/nlattr.c b/lib/nlattr.c index ac09f22..a8408b6 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -20,6 +20,7 @@ static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = { [NLA_U16] = sizeof(u16), [NLA_U32] = sizeof(u32), [NLA_U64] = sizeof(u64), + [NLA_MSECS] = sizeof(u64), [NLA_NESTED] = NLA_HDRLEN, }; -- cgit v0.10.2 From 4b6cc7284ddc9a54910f111085ebf0143ef3f5bd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 Nov 2011 00:10:05 +0000 Subject: netlink: clarify attribute length check documentation The documentation for how the length of attributes is checked is wrong ("Exact length" isn't true, the policy checks are for "minimum length") and a bit misleading. Make it more complete and explain what really happens. Cc: Thomas Graf Signed-off-by: Johannes Berg Signed-off-by: David S. Miller diff --git a/include/net/netlink.h b/include/net/netlink.h index 98c1854..cb1f350 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -192,8 +192,15 @@ enum { * NLA_NUL_STRING Maximum length of string (excluding NUL) * NLA_FLAG Unused * NLA_BINARY Maximum length of attribute payload - * NLA_NESTED_COMPAT Exact length of structure payload - * All other Exact length of attribute payload + * NLA_NESTED Don't use `len' field -- length verification is + * done by checking len of nested header (or empty) + * NLA_NESTED_COMPAT Minimum length of structure payload + * NLA_U8, NLA_U16, + * NLA_U32, NLA_U64, + * NLA_MSECS Leaving the length field zero will verify the + * given type fits, using it verifies minimum length + * just like "All other" + * All other Minimum length of attribute payload * * Example: * static const struct nla_policy my_policy[ATTR_MAX+1] = { -- cgit v0.10.2 From 27d240fdae2808d727ad9ce48ec029731a457524 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 4 Nov 2011 12:17:17 +0000 Subject: sky2: fix regression on Yukon Optima Changes to support other Optima types, introduced an accidental regression that caused 88E8059 to come up in 10Mbit/sec. The Yukon Optima supports a reverse auto-negotiation feature that was incorrectly setup, and not needed. The feature could be used to allow wake-on-lan at higher speeds. But doing it correctly would require other changes to initialization. Reported-by: Pavel Mateja Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index cbd026f..fdc6c39 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); } } else { - if (hw->chip_id >= CHIP_ID_YUKON_OPT) { - u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); - - /* enable PHY Reverse Auto-Negotiation */ - ctrl2 |= 1u << 13; - - /* Write PHY changes (SW-reset must follow) */ - gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); - } - - /* disable energy detect */ ctrl &= ~PHY_M_PC_EN_DET_MSK; -- cgit v0.10.2 From 589665f5a6008dbce1d0af2cb93e94a80bf78151 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 08:21:38 +0000 Subject: bonding: comparing a u8 with -1 is always false slave->duplex is a u8 type so the in bond_info_show_slave() when we check "if (slave->duplex == -1)", it's always false. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b2b9109..b0c5772 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -560,8 +560,8 @@ static int bond_update_speed_duplex(struct slave *slave) u32 slave_speed; int res; - slave->speed = -1; - slave->duplex = -1; + slave->speed = SPEED_UNKNOWN; + slave->duplex = DUPLEX_UNKNOWN; res = __ethtool_get_settings(slave_dev, &ecmd); if (res < 0) diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index d2ff52e..17206da 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c @@ -157,12 +157,12 @@ static void bond_info_show_slave(struct seq_file *seq, seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); seq_printf(seq, "MII Status: %s\n", (slave->link == BOND_LINK_UP) ? "up" : "down"); - if (slave->speed == -1) + if (slave->speed == SPEED_UNKNOWN) seq_printf(seq, "Speed: %s\n", "Unknown"); else seq_printf(seq, "Speed: %d Mbps\n", slave->speed); - if (slave->duplex == -1) + if (slave->duplex == DUPLEX_UNKNOWN) seq_printf(seq, "Duplex: %s\n", "Unknown"); else seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half"); diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 45f00b6..de33de1 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1097,10 +1097,12 @@ struct ethtool_ops { #define SPEED_1000 1000 #define SPEED_2500 2500 #define SPEED_10000 10000 +#define SPEED_UNKNOWN -1 /* Duplex, half or full. */ #define DUPLEX_HALF 0x00 #define DUPLEX_FULL 0x01 +#define DUPLEX_UNKNOWN 0xff /* Which connector port. */ #define PORT_TP 0x00 -- cgit v0.10.2 From 1a6422f67fbf691cf8721076619aeead9183403d Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 4 Nov 2011 12:58:41 +0000 Subject: etherh: Add MAINTAINERS entry for etherh During the re-organization of Ethernet drivers, the MAINTAINERS entry for etherh got dropped accidentally. CC: Russell King CC: Joe Perches Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index a6afe34..ecb2299 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1032,6 +1032,7 @@ F: arch/arm/include/asm/hardware/ioc.h F: arch/arm/include/asm/hardware/iomd.h F: arch/arm/include/asm/hardware/memc.h F: arch/arm/mach-rpc/ +F: drivers/net/ethernet/8390/etherh.c F: drivers/net/ethernet/i825xx/ether1* F: drivers/net/ethernet/seeq/ether3* F: drivers/scsi/arm/ -- cgit v0.10.2 From 012641082b34433dac3cbb452e0a6ceccfd4643f Mon Sep 17 00:00:00 2001 From: "Rose, Gregory V" Date: Mon, 7 Nov 2011 07:44:17 +0000 Subject: ixgbe: Fix compile for kernel without CONFIG_PCI_IOV defined Fix compiler errors and warnings with CONFIG_PCI_IOV defined and not defined. Signed-off-by: Greg Rose Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index db95731..00fcd39 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -442,12 +442,14 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter) { +#ifdef CONFIG_PCI_IOV int i; for (i = 0; i < adapter->num_vfs; i++) { if (adapter->vfinfo[i].vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) return true; } +#endif return false; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index 4a5d889..df04f1a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h @@ -42,11 +42,11 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); int ixgbe_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); -#ifdef CONFIG_PCI_IOV void ixgbe_disable_sriov(struct ixgbe_adapter *adapter); +int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter); +#ifdef CONFIG_PCI_IOV void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, const struct ixgbe_info *ii); -int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter); #endif -- cgit v0.10.2 From 23ba07991dad5a96a024c1b45cb602eef5f83df8 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 7 Nov 2011 05:54:58 +0000 Subject: usbnet: fix oops in usbnet_start_xmit This patch fixes the bug added in commit v3.1-rc7-1055-gf9b491e SKB can be NULL at this point, at least for cdc-ncm. Signed-off-by: Konstantin Khlebnikov Acked-by: Richard Cochran Signed-off-by: David S. Miller diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 7d60821..fae0fbd 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1057,7 +1057,8 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, unsigned long flags; int retval; - skb_tx_timestamp(skb); + if (skb) + skb_tx_timestamp(skb); // some devices want funky USB-level framing, for // win32 driver (usually) and/or hardware quirks -- cgit v0.10.2 From 039c811cb0e6c5696086072794bb79fc7011c765 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 7 Nov 2011 13:27:30 -0500 Subject: wanrouter: Remove kernel_lock annotations The BKL is gone, these annotations are useless. Signed-off-by: Richard Weinberger Signed-off-by: David S. Miller diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index f346395..c43612e 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -81,7 +81,6 @@ static struct proc_dir_entry *proc_router; * Iterator */ static void *r_start(struct seq_file *m, loff_t *pos) - __acquires(kernel_lock) { struct wan_device *wandev; loff_t l = *pos; @@ -103,7 +102,6 @@ static void *r_next(struct seq_file *m, void *v, loff_t *pos) } static void r_stop(struct seq_file *m, void *v) - __releases(kernel_lock) { mutex_unlock(&config_mutex); } -- cgit v0.10.2 From dd1294c4ed25725d13a6cb3d93ca0eb5fee14963 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Mon, 7 Nov 2011 13:28:20 -0500 Subject: MAINTAINERS/rds: update maintainer update for the actual maintainer Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index ecb2299..237c9ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5471,7 +5471,7 @@ S: Maintained F: drivers/net/ethernet/rdc/r6040.c RDS - RELIABLE DATAGRAM SOCKETS -M: Andy Grover +M: Venkat Venkatsubra L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported F: net/rds/ -- cgit v0.10.2 From f9c4082df59e43c6667db197a4fb3eb3286f3fc1 Mon Sep 17 00:00:00 2001 From: david decotigny Date: Sat, 5 Nov 2011 14:38:20 +0000 Subject: forcedeth: fix race when unloading module When forcedeth module is unloaded, there exists a path that can lead to mod_timer() after del_timer_sync(), causing an oops. This patch short-circuits this unneeded path, which originates in nv_get_ethtool_stats(). Tested: x86_64 16-way + 3 ethtool -S infinite loops + 100Mbps incoming traffic + rmmod/modprobe/ifconfig in a loop Initial-Author: Salman Qazi Discussion: http://patchwork.ozlabs.org/patch/123548/ Signed-off-by: David Decotigny Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 1e37eb9..344cb5f 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -4566,7 +4566,7 @@ static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *e struct fe_priv *np = netdev_priv(dev); /* update stats */ - nv_do_stats_poll((unsigned long)dev); + nv_get_hw_stats(dev); memcpy(buffer, &np->estats, nv_get_sset_count(dev, ETH_SS_STATS)*sizeof(u64)); } -- cgit v0.10.2 From 2a4e7a085fb44369c450c92cf8bd53b91f874a57 Mon Sep 17 00:00:00 2001 From: Mike Ditto Date: Sat, 5 Nov 2011 14:38:21 +0000 Subject: forcedeth: Acknowledge only interrupts that are being processed This is to avoid a race, accidentally acknowledging an interrupt that we didn't notice and won't immediately process. This is based solely on code inspection; it is not known if there was an actual bug here. Signed-off-by: David Decotigny Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 344cb5f..b7cf4b6 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -3398,7 +3398,8 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL; - writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus); + writel(events, base + NvRegMSIXIrqStatus); + netdev_dbg(dev, "tx irq events: %08x\n", events); if (!(events & np->irqmask)) break; @@ -3509,7 +3510,8 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; - writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); + writel(events, base + NvRegMSIXIrqStatus); + netdev_dbg(dev, "rx irq events: %08x\n", events); if (!(events & np->irqmask)) break; @@ -3553,7 +3555,8 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) for (i = 0;; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER; - writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus); + writel(events, base + NvRegMSIXIrqStatus); + netdev_dbg(dev, "irq events: %08x\n", events); if (!(events & np->irqmask)) break; @@ -3617,10 +3620,10 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) if (!(np->msi_flags & NV_MSI_X_ENABLED)) { events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; - writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus); + writel(events & NVREG_IRQ_TIMER, base + NvRegIrqStatus); } else { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; - writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus); + writel(events & NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus); } pci_push(base); if (!(events & NVREG_IRQ_TIMER)) -- cgit v0.10.2 From 4687f3f364a1d5b2df815a8c58a763cab57724e8 Mon Sep 17 00:00:00 2001 From: david decotigny Date: Sat, 5 Nov 2011 14:38:22 +0000 Subject: forcedeth: remove unneeded stats updates Function ndo_get_stats() updates most of the stats from hardware registers, making the manual updates un-needed. This change removes these manual updates. Main exception is rx_missed_errors which needs manual update. Another exception is rx_packets, still updated manually in this commit to make sure this patch doesn't change behavior of driver. This will be addressed by a future patch. Signed-off-by: David Decotigny Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index b7cf4b6..2f1eaee 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -2374,16 +2374,8 @@ static int nv_tx_done(struct net_device *dev, int limit) if (np->desc_ver == DESC_VER_1) { if (flags & NV_TX_LASTPACKET) { if (flags & NV_TX_ERROR) { - if (flags & NV_TX_UNDERFLOW) - dev->stats.tx_fifo_errors++; - if (flags & NV_TX_CARRIERLOST) - dev->stats.tx_carrier_errors++; if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK)) nv_legacybackoff_reseed(dev); - dev->stats.tx_errors++; - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; @@ -2392,16 +2384,8 @@ static int nv_tx_done(struct net_device *dev, int limit) } else { if (flags & NV_TX2_LASTPACKET) { if (flags & NV_TX2_ERROR) { - if (flags & NV_TX2_UNDERFLOW) - dev->stats.tx_fifo_errors++; - if (flags & NV_TX2_CARRIERLOST) - dev->stats.tx_carrier_errors++; if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) nv_legacybackoff_reseed(dev); - dev->stats.tx_errors++; - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += np->get_tx_ctx->skb->len; } dev_kfree_skb_any(np->get_tx_ctx->skb); np->get_tx_ctx->skb = NULL; @@ -2434,9 +2418,7 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit) nv_unmap_txskb(np, np->get_tx_ctx); if (flags & NV_TX2_LASTPACKET) { - if (!(flags & NV_TX2_ERROR)) - dev->stats.tx_packets++; - else { + if (flags & NV_TX2_ERROR) { if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) { if (np->driver_data & DEV_HAS_GEAR_MODE) nv_gear_backoff_reseed(dev); @@ -2636,7 +2618,6 @@ static int nv_rx_process(struct net_device *dev, int limit) if ((flags & NV_RX_ERROR_MASK) == NV_RX_ERROR4) { len = nv_getlen(dev, skb->data, len); if (len < 0) { - dev->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2650,11 +2631,6 @@ static int nv_rx_process(struct net_device *dev, int limit) else { if (flags & NV_RX_MISSEDFRAME) dev->stats.rx_missed_errors++; - if (flags & NV_RX_CRCERR) - dev->stats.rx_crc_errors++; - if (flags & NV_RX_OVERFLOW) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2670,7 +2646,6 @@ static int nv_rx_process(struct net_device *dev, int limit) if ((flags & NV_RX2_ERROR_MASK) == NV_RX2_ERROR4) { len = nv_getlen(dev, skb->data, len); if (len < 0) { - dev->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2682,11 +2657,6 @@ static int nv_rx_process(struct net_device *dev, int limit) } /* the rest are hard errors */ else { - if (flags & NV_RX2_CRCERR) - dev->stats.rx_crc_errors++; - if (flags & NV_RX2_OVERFLOW) - dev->stats.rx_over_errors++; - dev->stats.rx_errors++; dev_kfree_skb(skb); goto next_pkt; } @@ -2704,7 +2674,6 @@ static int nv_rx_process(struct net_device *dev, int limit) skb->protocol = eth_type_trans(skb, dev); napi_gro_receive(&np->napi, skb); dev->stats.rx_packets++; - dev->stats.rx_bytes += len; next_pkt: if (unlikely(np->get_rx.orig++ == np->last_rx.orig)) np->get_rx.orig = np->first_rx.orig; @@ -2787,9 +2756,7 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) __vlan_hwaccel_put_tag(skb, vid); } napi_gro_receive(&np->napi, skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; } else { dev_kfree_skb(skb); } -- cgit v0.10.2 From 0bdfea8ba856826f5901fda608013f323c87f661 Mon Sep 17 00:00:00 2001 From: Mandeep Baines Date: Sat, 5 Nov 2011 14:38:23 +0000 Subject: forcedeth: Improve stats counters Rx byte count was off; instead use the hardware's count. Tx packet count was counting pre-TSO packets; instead count on-the-wire packets. Report hardware dropped frame count as rx_fifo_errors. - The count of transmitted packets reported by the forcedeth driver reports pre-TSO (TCP Segmentation Offload) packet counts and not the count of the number of packets sent on the wire. This change fixes the forcedeth driver to report the correct count. Fixed the code by copying the count stored in the NIC H/W to the value reported by the driver. - Count rx_drop_frame errors as rx_fifo_errors: We see a lot of rx_drop_frame errors if we disable the rx bottom-halves for too long. Normally, rx_fifo_errors would be counted in this case. The rx_drop_frame error count is private to forcedeth and is not reported by ifconfig or sysfs. The rx_fifo_errors count is currently unused in the forcedeth driver. It is reported by ifconfig as overruns. This change reports rx_drop_frame errors as rx_fifo_errors. Signed-off-by: David Decotigny Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 2f1eaee..0c10ff7 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -1682,6 +1682,7 @@ static void nv_get_hw_stats(struct net_device *dev) np->estats.tx_pause += readl(base + NvRegTxPause); np->estats.rx_pause += readl(base + NvRegRxPause); np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame); + np->estats.rx_errors_total += np->estats.rx_drop_frame; } if (np->driver_data & DEV_HAS_STATISTICS_V3) { @@ -1706,11 +1707,14 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) nv_get_hw_stats(dev); /* copy to net_device stats */ + dev->stats.tx_packets = np->estats.tx_packets; + dev->stats.rx_bytes = np->estats.rx_bytes; dev->stats.tx_bytes = np->estats.tx_bytes; dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors; dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors; dev->stats.rx_crc_errors = np->estats.rx_crc_errors; dev->stats.rx_over_errors = np->estats.rx_over_errors; + dev->stats.rx_fifo_errors = np->estats.rx_drop_frame; dev->stats.rx_errors = np->estats.rx_errors_total; dev->stats.tx_errors = np->estats.tx_errors_total; } -- cgit v0.10.2 From e45a618753d5a8bc9086382f73bbc2d6a3399250 Mon Sep 17 00:00:00 2001 From: david decotigny Date: Sat, 5 Nov 2011 14:38:24 +0000 Subject: forcedeth: fix a few sparse warnings (variable shadowing) This fixes the following sparse warnings: drivers/net/ethernet/nvidia/forcedeth.c:2113:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2102:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2155:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2102:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2227:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2215:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2271:7: warning: symbol 'size' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2215:6: originally declared here drivers/net/ethernet/nvidia/forcedeth.c:2986:20: warning: symbol 'addr' shadows an earlier one drivers/net/ethernet/nvidia/forcedeth.c:2963:6: originally declared here Signed-off-by: David Decotigny Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 0c10ff7..1dca570 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -2103,10 +2103,10 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) /* add fragments to entries count */ for (i = 0; i < fragments; i++) { - u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + u32 frag_size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - entries += (size >> NV_TX2_TSO_MAX_SHIFT) + - ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); + entries += (frag_size >> NV_TX2_TSO_MAX_SHIFT) + + ((frag_size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); } spin_lock_irqsave(&np->lock, flags); @@ -2145,13 +2145,13 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) /* setup the fragments */ for (i = 0; i < fragments; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = skb_frag_size(frag); + u32 frag_size = skb_frag_size(frag); offset = 0; do { prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; np->put_tx_ctx->dma = skb_frag_dma_map( &np->pci_dev->dev, frag, offset, @@ -2163,12 +2163,12 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); offset += bcnt; - size -= bcnt; + frag_size -= bcnt; if (unlikely(put_tx++ == np->last_tx.orig)) put_tx = np->first_tx.orig; if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) np->put_tx_ctx = np->first_tx_ctx; - } while (size); + } while (frag_size); } /* set last fragment flag */ @@ -2217,10 +2217,10 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, /* add fragments to entries count */ for (i = 0; i < fragments; i++) { - u32 size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + u32 frag_size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - entries += (size >> NV_TX2_TSO_MAX_SHIFT) + - ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); + entries += (frag_size >> NV_TX2_TSO_MAX_SHIFT) + + ((frag_size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); } spin_lock_irqsave(&np->lock, flags); @@ -2261,13 +2261,13 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, /* setup the fragments */ for (i = 0; i < fragments; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = skb_frag_size(frag); + u32 frag_size = skb_frag_size(frag); offset = 0; do { prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; np->put_tx_ctx->dma = skb_frag_dma_map( &np->pci_dev->dev, frag, offset, @@ -2280,12 +2280,12 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); offset += bcnt; - size -= bcnt; + frag_size -= bcnt; if (unlikely(put_tx++ == np->last_tx.ex)) put_tx = np->first_tx.ex; if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) np->put_tx_ctx = np->first_tx_ctx; - } while (size); + } while (frag_size); } /* set last fragment flag */ @@ -2933,11 +2933,11 @@ static void nv_set_multicast(struct net_device *dev) struct netdev_hw_addr *ha; netdev_for_each_mc_addr(ha, dev) { - unsigned char *addr = ha->addr; + unsigned char *hw_addr = ha->addr; u32 a, b; - a = le32_to_cpu(*(__le32 *) addr); - b = le16_to_cpu(*(__le16 *) (&addr[4])); + a = le32_to_cpu(*(__le32 *) hw_addr); + b = le16_to_cpu(*(__le16 *) (&hw_addr[4])); alwaysOn[0] &= a; alwaysOff[0] &= ~a; alwaysOn[1] &= b; -- cgit v0.10.2