From 2f81b47135a971a22ccad9f3cc8c68a583b93ea4 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 11 Aug 2010 16:11:00 -0400 Subject: ipw2100: register pm_qos request before registering pci driver It is necessary to call pm_qos_add_request prior to calling pm_qos_update_request. It was revealed that ipw2100 has been doing this wrong since "pm_qos: Get rid of the allocation in pm_qos_add_request()" (commit 82f682514a5df89ffb3890627eebf0897b7a84ec) added a WARN that results in the following backtrace: WARNING: at kernel/pm_qos_params.c:264 pm_qos_update_request+0x5e/0x70() pm_qos_update_request() called for unknown object Call Trace: [] ? warn_slowpath_common+0x78/0xb0 [] ? pm_qos_update_request+0x5e/0x70 [] ? pm_qos_update_request+0x5e/0x70 [] ? warn_slowpath_fmt+0x33/0x40 [] ? pm_qos_update_request+0x5e/0x70 [] ? ipw2100_up+0x3f/0xf10 [ipw2100] [] ? vsnprintf+0xc9/0x530 [] ? ipw2100_net_init+0x2c/0x1c0 [ipw2100] [] ? register_netdevice+0x7d/0x3c0 [] ? ipw2100_irq_tasklet+0x910/0x9a0 [ipw2100] [] ? register_netdev+0x2f/0x40 [] ? ipw2100_pci_init_one+0xd21/0x1060 [ipw2100] [] ? local_pci_probe+0xb/0x10 [] ? pci_device_probe+0x69/0x90 [] ? driver_probe_device+0x74/0x180 [] ? sysfs_create_dir+0x6a/0xb0 [] ? __driver_attach+0x79/0x80 [] ? __driver_attach+0x0/0x80 [] ? bus_for_each_dev+0x52/0x80 [] ? driver_attach+0x16/0x20 [] ? __driver_attach+0x0/0x80 [] ? bus_add_driver+0x17f/0x250 [] ? pci_device_shutdown+0x0/0x20 [] ? pci_device_remove+0x0/0x40 [] ? driver_register+0x63/0x120 [] ? __pci_register_driver+0x36/0xa0 [] ? ipw2100_init+0x48/0x67 [ipw2100] [] ? do_one_initcall+0x32/0x170 [] ? __vunmap+0xb8/0xf0 [] ? ipw2100_init+0x0/0x67 [ipw2100] [] ? sys_init_module+0x161/0x1000 [] ? sys_close+0x67/0xe0 [] ? syscall_call+0x7/0xb This patch moves pm_qos_add_request prior to pci_register_driver in ipw2100 in order to avoid this problem. Reported-by: Christoph Fritz Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 16bbfa3189a..1189dbb6e2a 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6665,12 +6665,13 @@ static int __init ipw2100_init(void) printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); + pm_qos_add_request(&ipw2100_pm_qos_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + ret = pci_register_driver(&ipw2100_pci_driver); if (ret) goto out; - pm_qos_add_request(&ipw2100_pm_qos_req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); #ifdef CONFIG_IPW2100_DEBUG ipw2100_debug_level = debug; ret = driver_create_file(&ipw2100_pci_driver.driver, -- cgit v1.2.3-70-g09d2 From da93f10684bfba2983a70c10b5d417232b6a5245 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 11 Aug 2010 20:27:43 +0530 Subject: ath9k_htc: fix panic on packet injection using airbase-ng tool. This should fix the oops which occurs during the packet injection on monitor interface. EIP is at ath9k_htc_tx_start+0x69/0x220 [ath9k_htc] [] ? invoke_tx_handlers+0xa5a/0xee0 [mac80211] [] ? ath9k_htc_tx+0x44/0xe0 [ath9k_htc] [] ? __ieee80211_tx+0xf8/0x190 [mac80211] [] ? ieee80211_tx+0x9d/0x1a0 [mac80211] [] ? ieee80211_xmit+0x9c/0x1c0 [mac80211] [] ? ieee80211_monitor_start_xmit+0x85/0xb0 [mac80211] [] ? dev_hard_start_xmit+0x1ad/0x210 [] ? __alloc_skb+0x52/0x130 [] ? sch_direct_xmit+0x105/0x170 [] ? dev_queue_xmit+0x37f/0x4b0 [] ? packet_snd+0x21e/0x250 [] ? packet_sendmsg+0x32/0x40 [] ? sock_aio_write+0x113/0x130 [] ? do_sync_write+0xc4/0x100 [] ? autoremove_wake_function+0x0/0x50 [] ? security_file_permission+0x14/0x20 [] ? rw_verify_area+0x64/0xe0 [] ? handle_mm_fault+0x338/0x390 [] ? vfs_write+0x185/0x1a0 [] ? do_page_fault+0x160/0x3a0 [] ? sys_write+0x42/0x70 [] ? syscall_call+0x7/0xb Signed-off-by: Rajkumar Manoharan Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index bd0b4acc3ec..2a6e45a293a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -78,18 +78,23 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ath9k_htc_sta *ista; - struct ath9k_htc_vif *avp; struct ath9k_htc_tx_ctl tx_ctl; enum htc_endpoint_id epid; u16 qnum; __le16 fc; u8 *tx_fhdr; - u8 sta_idx; + u8 sta_idx, vif_idx; hdr = (struct ieee80211_hdr *) skb->data; fc = hdr->frame_control; - avp = (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv; + if (tx_info->control.vif && + (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv) + vif_idx = ((struct ath9k_htc_vif *) + tx_info->control.vif->drv_priv)->index; + else + vif_idx = priv->nvifs; + if (sta) { ista = (struct ath9k_htc_sta *) sta->drv_priv; sta_idx = ista->index; @@ -106,7 +111,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); tx_hdr.node_idx = sta_idx; - tx_hdr.vif_idx = avp->index; + tx_hdr.vif_idx = vif_idx; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_ctl.type = ATH9K_HTC_AMPDU; @@ -169,7 +174,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) tx_ctl.type = ATH9K_HTC_NORMAL; mgmt_hdr.node_idx = sta_idx; - mgmt_hdr.vif_idx = avp->index; + mgmt_hdr.vif_idx = vif_idx; mgmt_hdr.tidno = 0; mgmt_hdr.flags = 0; -- cgit v1.2.3-70-g09d2 From 71ba186c123630ddab17667ec9ecf7e2ef211295 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 12 Aug 2010 14:23:28 +0530 Subject: ath9k_htc: Fix disconnect issue in HT40 mode. Some APs advertise that they may be HT40 capable in the capabilites but the current operating channel configuration may be only HT20. This causes disconnection as ath9k_htc sets WLAN_RC_40_FLAG despite the AP operating in HT20 mode. Hence set this flag only if the current channel configuration is HT40 enabled. Cc: stable@kernel.org Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ebed9d1691a..7d09b4b17bb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -366,7 +366,8 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, caps = WLAN_RC_HT_FLAG; if (sta->ht_cap.mcs.rx_mask[1]) caps |= WLAN_RC_DS_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && + (conf_is_ht40(&priv->hw->conf))) caps |= WLAN_RC_40_FLAG; if (conf_is_ht40(&priv->hw->conf) && (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) -- cgit v1.2.3-70-g09d2 From fe0dbcc9d2e941328b3269dab102b94ad697ade5 Mon Sep 17 00:00:00 2001 From: Yuri Kululin Date: Fri, 13 Aug 2010 13:46:12 +0400 Subject: wl1251: fix trigger scan timeout usage Use appropriate command (CMD_TRIGGER_SCAN_TO) instead of scan command (CMD_SCAN) to configure trigger scan timeout. This was broken in commit 3a98c30f3e8bb1f32b5bcb74a39647b3670de275. This fix address the bug reported here: https://bugzilla.kernel.org/show_bug.cgi?id=16554 Cc: stable@kernel.org Signed-off-by: Yuri Ershov Signed-off-by: Yuri Kululin Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index a37b30cef48..ce3722f4c3e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c @@ -484,7 +484,7 @@ int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) cmd->timeout = timeout; - ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); + ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("cmd trigger scan to failed: %d", ret); goto out; -- cgit v1.2.3-70-g09d2 From ca6cff1f80f30cc6313a943339361ad6f9e76548 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 13 Aug 2010 18:36:40 +0530 Subject: ath9k_htc: load proper firmware for device ID 7015 This patch handles the firmware loading properly for device ID 7015. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.h | 1 + drivers/net/wireless/ath/ath9k/eeprom_9287.c | 7 ++++++- drivers/net/wireless/ath/ath9k/hif_usb.c | 8 ++------ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + drivers/net/wireless/ath/ath9k/reg.h | 1 + 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 8750c558c22..7f48df1e290 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -191,6 +191,7 @@ #define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 #define AR9287_EEP_START_LOC 128 +#define AR9287_HTC_EEP_START_LOC 256 #define AR9287_NUM_2G_CAL_PIERS 3 #define AR9287_NUM_2G_CCK_TARGET_POWERS 3 #define AR9287_NUM_2G_20_TARGET_POWERS 3 diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 4a52cf03808..dff2da77731 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -34,9 +34,14 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct ath_common *common = ath9k_hw_common(ah); u16 *eep_data; - int addr, eep_start_loc = AR9287_EEP_START_LOC; + int addr, eep_start_loc; eep_data = (u16 *)eep; + if (ah->hw_version.devid == 0x7015) + eep_start_loc = AR9287_HTC_EEP_START_LOC; + else + eep_start_loc = AR9287_EEP_START_LOC; + if (!ath9k_hw_use_flash(ah)) { ath_print(common, ATH_DBG_EEPROM, "Reading from EEPROM, not flash\n"); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 61c1bee3f26..17e7a9a367e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -799,7 +799,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) } kfree(buf); - if (hif_dev->device_id == 0x7010) + if ((hif_dev->device_id == 0x7010) || (hif_dev->device_id == 0x7015)) firm_offset = AR7010_FIRMWARE_TEXT; else firm_offset = AR9271_FIRMWARE_TEXT; @@ -901,6 +901,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, switch(hif_dev->device_id) { case 0x7010: + case 0x7015: case 0x9018: if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) hif_dev->fw_name = FIRMWARE_AR7010_1_1; @@ -912,11 +913,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, break; } - if (!hif_dev->fw_name) { - dev_err(&udev->dev, "Can't determine firmware !\n"); - goto err_htc_hw_alloc; - } - ret = ath9k_hif_usb_dev_init(hif_dev); if (ret) { ret = -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 148b43317fd..2d4279191d7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -245,6 +245,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) switch(devid) { case 0x7010: + case 0x7015: case 0x9018: priv->htc->credits = 45; break; diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 633e3d949ec..d01c4adab8d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -899,6 +899,7 @@ #define AR_DEVID_7010(_ah) \ (((_ah)->hw_version.devid == 0x7010) || \ + ((_ah)->hw_version.devid == 0x7015) || \ ((_ah)->hw_version.devid == 0x9018)) #define AR_RADIO_SREV_MAJOR 0xf0 -- cgit v1.2.3-70-g09d2 From 6ccf15a1a76d2ff915cdef6ae4d12d0170087118 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Fri, 13 Aug 2010 11:27:28 -0400 Subject: ath5k: disable ASPM L0s for all cards Atheros PCIe wireless cards handled by ath5k do require L0s disabled. For distributions shipping with CONFIG_PCIEASPM (this will be enabled by default in the future in 2.6.36) this will also mean both L1 and L0s will be disabled when a pre 1.1 PCIe device is detected. We do know L1 works correctly even for all ath5k pre 1.1 PCIe devices though but cannot currently undue the effect of a blacklist, for details you can read pcie_aspm_sanity_check() and see how it adjusts the device link capability. It may be possible in the future to implement some PCI API to allow drivers to override blacklists for pre 1.1 PCIe but for now it is best to accept that both L0s and L1 will be disabled completely for distributions shipping with CONFIG_PCIEASPM rather than having this issue present. Motivation for adding this new API will be to help with power consumption for some of these devices. Example of issues you'd see: - On the Acer Aspire One (AOA150, Atheros Communications Inc. AR5001 Wireless Network Adapter [168c:001c] (rev 01)) doesn't work well with ASPM enabled, the card will eventually stall on heavy traffic with often 'unsupported jumbo' warnings appearing. Disabling ASPM L0s in ath5k fixes these problems. - On the same card you would see a storm of RXORN interrupts even though medium is idle. Credit for root causing and fixing the bug goes to Jussi Kivilinna. Cc: David Quan Cc: Matthew Garrett Cc: Tim Gardner Cc: Jussi Kivilinna Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: Maxim Levitsky Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0d5de2574dd..373dcfec689 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -476,6 +477,26 @@ ath5k_pci_probe(struct pci_dev *pdev, int ret; u8 csz; + /* + * L0s needs to be disabled on all ath5k cards. + * + * For distributions shipping with CONFIG_PCIEASPM (this will be enabled + * by default in the future in 2.6.36) this will also mean both L1 and + * L0s will be disabled when a pre 1.1 PCIe device is detected. We do + * know L1 works correctly even for all ath5k pre 1.1 PCIe devices + * though but cannot currently undue the effect of a blacklist, for + * details you can read pcie_aspm_sanity_check() and see how it adjusts + * the device link capability. + * + * It may be possible in the future to implement some PCI API to allow + * drivers to override blacklists for pre 1.1 PCIe but for now it is + * best to accept that both L0s and L1 will be disabled completely for + * distributions shipping with CONFIG_PCIEASPM rather than having this + * issue present. Motivation for adding this new API will be to help + * with power consumption for some of these devices. + */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "can't enable device\n"); -- cgit v1.2.3-70-g09d2 From ce60659ad838a77d71aa817a6781659799970ae1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 23 Jul 2010 13:19:39 -0700 Subject: iwlwifi: long monitor timer Change the name for monitor timer, also adding define for long monitor timer; long monitor timer can be used for the type of devices require longer time to determine the uCode is stuck on tx and needed reload. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-6000.c | 32 ++++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++- 6 files changed, 30 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index fec02621232..0b779a41a14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -265,7 +265,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -297,7 +297,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6950a783913..8ccfcd08218 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2731,7 +2731,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, }; @@ -2752,7 +2752,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d6da356608f..d92b7290923 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2322,7 +2322,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .temperature_kelvin = true, .max_event_log_size = 512, .tx_power_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aacf3770f07..cd9f9fc53f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -510,7 +510,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -541,7 +541,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -601,7 +601,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -632,7 +632,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -663,7 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -693,7 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index af4fd50f340..b6468e96211 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -388,7 +388,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -424,7 +424,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -459,7 +459,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -496,7 +496,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -532,7 +532,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -606,7 +606,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -644,7 +644,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -680,7 +680,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -721,7 +721,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -756,7 +756,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -791,7 +791,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -828,7 +828,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -866,7 +866,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -902,7 +902,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -940,7 +940,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f35bcad56e3..2e97cd2fa98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1049,7 +1049,8 @@ struct iwl_event_log { #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) /* timer constants use to monitor and recover stuck tx queues in mSecs */ -#define IWL_MONITORING_PERIOD (1000) +#define IWL_DEF_MONITORING_PERIOD (1000) +#define IWL_LONG_MONITORING_PERIOD (5000) #define IWL_ONE_HUNDRED_MSECS (100) #define IWL_SIXTY_SECS (60000) -- cgit v1.2.3-70-g09d2 From 3198c68cb4e1967f59244f0a0b9f46102d617373 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 23 Jul 2010 13:19:40 -0700 Subject: iwlwifi: use long monitor timer to avoid un-necessary reload For 5000 and 6000g2b series of devices, use long monitor timer to check stuck tx queues. .6000g2b series device, it is WiFi/BT combo device, there are some cases, tx queues are not move for a period of time because the WiFi/BT coex. .5000 series device, it is being reported firmware got reload more often than necessary, so extend the timer to avoid un-necessary reload. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-5000.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-6000.c | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index cd9f9fc53f8..0cbefa3d1e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -510,7 +510,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -541,7 +541,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -601,7 +601,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -632,7 +632,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b6468e96211..cee06b968de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -496,7 +496,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -532,7 +532,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -606,7 +606,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -644,7 +644,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -680,7 +680,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, -- cgit v1.2.3-70-g09d2 From c206a04fba2c3890bc95dc9c20ae2cf9740fae71 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 13 Aug 2010 18:47:33 -0400 Subject: ipw2100: don't sync status queue entries These are allocated with pci_alloc_consistent, so calling pci_dma_sync_single_for_cpu is incorrect usage of the API. Remove this misuse and consequently avoid the following backtrace: WARNING: at lib/dma-debug.c:902 check_sync+0xce/0x43a() Hardware name: 2373HU6 ipw2100 0000:02:02.0: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x0000000034e88008] [size=8 bytes] Modules linked in: microcode ipw2100(+) snd_seq_device ppdev libipw nsc_ircc snd_pcm lib80211 video output irda parport_pc cfg80211 parport thinkpad_acpi e1000 iTCO_wdt crc_ccitt snd_timer iTCO_vendor_support snd i2c_i801 pcspkr rfkill soundcore joydev snd_page_alloc yenta_socket radeon ttm drm_kms_helper drm i2c_algo_bit i2c_core [last unloaded: scsi_wait_scan] Pid: 0, comm: swapper Tainted: G W 2.6.35-wl+ #8 Call Trace: [] warn_slowpath_common+0x6a/0x7f [] ? check_sync+0xce/0x43a [] warn_slowpath_fmt+0x2b/0x2f [] check_sync+0xce/0x43a [] ? print_lock_contention_bug+0x11/0xb2 [] debug_dma_sync_single_for_cpu+0x47/0x49 [] ? ehci_irq+0x31/0x331 [] ? ipw2100_irq_tasklet+0x24/0x5e9 [ipw2100] [] ? ipw2100_irq_tasklet+0x24/0x5e9 [ipw2100] [] pci_dma_sync_single_for_cpu.clone.1+0x42/0x4b [ipw2100] [] ipw2100_irq_tasklet+0x17c/0x5e9 [ipw2100] [] tasklet_action+0x78/0xcb [] __do_softirq+0xc4/0x183 [] do_softirq+0x3b/0x5f [] irq_exit+0x3a/0x6d [] do_IRQ+0x8b/0x9f [] common_interrupt+0x35/0x3c [] ? acpi_idle_enter_simple+0xfe/0x13c [] ? exit_itimers+0x2d/0x73 [] ? acpi_idle_enter_simple+0x100/0x13c [] cpuidle_idle_call+0x78/0xdc [] cpu_idle+0x9b/0xb7 [] rest_init+0xa6/0xab [] start_kernel+0x389/0x38e [] i386_start_kernel+0xc9/0xd0 Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 1189dbb6e2a..996e9d7d758 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2723,14 +2723,6 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv) packet = &priv->rx_buffers[i]; - /* Sync the DMA for the STATUS buffer so CPU is sure to get - * the correct values */ - pci_dma_sync_single_for_cpu(priv->pci_dev, - sq->nic + - sizeof(struct ipw2100_status) * i, - sizeof(struct ipw2100_status), - PCI_DMA_FROMDEVICE); - /* Sync the DMA for the RX buffer so CPU is sure to get * the correct values */ pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr, -- cgit v1.2.3-70-g09d2 From 8b8ab9d5e352aae0dcae53c657b25ab61bb73f0f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 17 Aug 2010 11:24:01 +0200 Subject: iwlwifi: fix 3945 filter flags Applying the filter flags directly as done since commit 3474ad635db371b0d8d0ee40086f15d223d5b6a4 Author: Johannes Berg Date: Thu Apr 29 04:43:05 2010 -0700 iwlwifi: apply filter flags directly broke 3945 under some unknown circumstances, as reported by Alex. Since I want to keep the direct application of filter flags on iwlagn, duplicate the code into both 3945 and agn and remove committing the RXON that broke things from the 3945 version. Cc: stable@kernel.org [2.6.35] Reported-by: Alex Romosan Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 45 ++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.c | 45 ------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 51 ++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c1882fd8345..10d7b9b7f06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3667,6 +3667,49 @@ out_exit: IWL_DEBUG_MAC80211(priv, "leave\n"); } +static void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + iwlcore_commit_rxon(priv); + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; @@ -3867,7 +3910,7 @@ static struct ieee80211_ops iwl_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwlagn_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, .conf_tx = iwl_mac_conf_tx, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2c03c6e20a7..07dbc279644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1328,51 +1328,6 @@ out: EXPORT_SYMBOL(iwl_apm_init); - -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct iwl_priv *priv = hw->priv; - __le32 filter_or = 0, filter_nand = 0; - -#define CHK(test, flag) do { \ - if (*total_flags & (test)) \ - filter_or |= (flag); \ - else \ - filter_nand |= (flag); \ - } while (0) - - IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); - CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); - CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); - -#undef CHK - - mutex_lock(&priv->mutex); - - priv->staging_rxon.filter_flags &= ~filter_nand; - priv->staging_rxon.filter_flags |= filter_or; - - iwlcore_commit_rxon(priv); - - mutex_unlock(&priv->mutex); - - /* - * Receiving all multicast frames is always enabled by the - * default flags setup in iwl_connection_init_rx_config() - * since we currently do not support programming multicast - * filters into the device. - */ - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} -EXPORT_SYMBOL(iwl_configure_filter); - int iwl_set_hw_params(struct iwl_priv *priv) { priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4a71dfb10a1..5e6ee3da6bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -372,9 +372,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, u32 decrypt_res, struct ieee80211_rx_status *stats); void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast); int iwl_set_hw_params(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_bss_info_changed(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 70c4b8fba0e..59a308b02f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3391,6 +3391,55 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, return 0; } + +static void iwl3945_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + /* + * Committing directly here breaks for some reason, + * but we'll eventually commit the filter flags + * change anyway. + */ + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + + /***************************************************************************** * * sysfs attributes @@ -3796,7 +3845,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, -- cgit v1.2.3-70-g09d2 From 5db5584441c2dceb75696fb31a44ac7b9b925359 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 11 Aug 2010 19:11:19 -0700 Subject: drivers/net/wireless: Restore upper case words in wiphy_ messages Commit c96c31e499b70964cfc88744046c998bb710e4b8 "(drivers/net/wireless: Use wiphy_)" inadvertently changed some upper case words to lower case. Restore the original case. Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 8 +++--- drivers/net/wireless/at76c50x-usb.c | 22 ++++++++--------- drivers/net/wireless/ath/ar9170/main.c | 4 +-- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/mwl8k.c | 34 +++++++++++++------------- drivers/net/wireless/p54/eeprom.c | 6 ++--- drivers/net/wireless/p54/fwio.c | 2 +- drivers/net/wireless/p54/led.c | 4 +-- drivers/net/wireless/p54/p54pci.c | 2 +- drivers/net/wireless/p54/txrx.c | 2 +- drivers/net/wireless/rtl818x/rtl8180_dev.c | 6 ++--- drivers/net/wireless/rtl818x/rtl8187_dev.c | 4 +-- drivers/net/wireless/rtl818x/rtl8187_rtl8225.c | 4 +-- 13 files changed, 50 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index a105087af96..f9aa1bc0a94 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -732,7 +732,7 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) /* Nothing to do for ADMtek BBP */ } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) - wiphy_debug(dev->wiphy, "unsupported bbp type %d\n", + wiphy_debug(dev->wiphy, "unsupported BBP type %d\n", priv->bbp_type); ADM8211_RESTORE(); @@ -1032,7 +1032,7 @@ static int adm8211_hw_init_bbp(struct ieee80211_hw *dev) break; } } else - wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type); + wiphy_debug(dev->wiphy, "unsupported BBP %d\n", priv->bbp_type); ADM8211_CSR_WRITE(SYNRF, 0); @@ -1525,7 +1525,7 @@ static int adm8211_start(struct ieee80211_hw *dev) retval = request_irq(priv->pdev->irq, adm8211_interrupt, IRQF_SHARED, "adm8211", dev); if (retval) { - wiphy_err(dev->wiphy, "failed to register irq handler\n"); + wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); goto fail; } @@ -1902,7 +1902,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, goto err_free_eeprom; } - wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n", + wiphy_info(dev->wiphy, "hwaddr %pM, Rev 0x%02x\n", dev->wiphy->perm_addr, pdev->revision); return 0; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index d5140a87f07..1128fa8c9ed 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -655,7 +655,7 @@ static int at76_get_hw_config(struct at76_priv *priv) exit: kfree(hwcfg); if (ret < 0) - wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n", + wiphy_err(priv->hw->wiphy, "cannot get HW Config (error %d)\n", ret); return ret; @@ -960,7 +960,7 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv) sizeof(struct mib_mac_addr)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_addr) failed: %d\n", ret); + "at76_get_mib (MAC_ADDR) failed: %d\n", ret); goto exit; } @@ -989,7 +989,7 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv) sizeof(struct mib_mac_wep)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_wep) failed: %d\n", ret); + "at76_get_mib (MAC_WEP) failed: %d\n", ret); goto exit; } @@ -1026,7 +1026,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) sizeof(struct mib_mac_mgmt)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_mgmt) failed: %d\n", ret); + "at76_get_mib (MAC_MGMT) failed: %d\n", ret); goto exit; } @@ -1062,7 +1062,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac) failed: %d\n", ret); + "at76_get_mib (MAC) failed: %d\n", ret); goto exit; } @@ -1099,7 +1099,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (phy) failed: %d\n", ret); + "at76_get_mib (PHY) failed: %d\n", ret); goto exit; } @@ -1132,7 +1132,7 @@ static void at76_dump_mib_local(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (local) failed: %d\n", ret); + "at76_get_mib (LOCAL) failed: %d\n", ret); goto exit; } @@ -1158,7 +1158,7 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv) sizeof(struct mib_mdomain)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mdomain) failed: %d\n", ret); + "at76_get_mib (MDOMAIN) failed: %d\n", ret); goto exit; } @@ -1229,7 +1229,7 @@ static int at76_submit_rx_urb(struct at76_priv *priv) struct sk_buff *skb = priv->rx_skb; if (!priv->rx_urb) { - wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n", + wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is NULL\n", __func__); return -EFAULT; } @@ -1792,7 +1792,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret); if (ret == -EINVAL) wiphy_err(priv->hw->wiphy, - "-einval: tx urb %p hcpriv %p complete %p\n", + "-EINVAL: tx urb %p hcpriv %p complete %p\n", priv->tx_urb, priv->tx_urb->hcpriv, priv->tx_urb->complete); } @@ -2310,7 +2310,7 @@ static int at76_init_new_device(struct at76_priv *priv, priv->mac80211_registered = 1; - wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n", + wiphy_info(priv->hw->wiphy, "USB %s, MAC %pM, firmware %d.%d.%d-%d\n", dev_name(&interface->dev), priv->mac_addr, priv->fw_version.major, priv->fw_version.minor, priv->fw_version.patch, priv->fw_version.build); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c67b05f3bcb..debfb0fbc7c 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -245,7 +245,7 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) { int i; - wiphy_debug(ar->hw->wiphy, "qos queue stats\n"); + wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); for (i = 0; i < __AR9170_NUM_TXQ; i++) wiphy_debug(ar->hw->wiphy, @@ -387,7 +387,7 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { #ifdef AR9170_QUEUE_DEBUG wiphy_debug(ar->hw->wiphy, - "skip frame => da %pm != %pm\n", + "skip frame => DA %pM != %pM\n", mac, ieee80211_get_DA(hdr)); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 01ad7f77383..86fa8abdd66 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -486,7 +486,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct ieee80211_rx_status rx_status; if (data->idle) { - wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n"); + wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); return false; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d761ed2d8af..f152a25be59 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -910,14 +910,14 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); if (rxq->rxd == NULL) { - wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n"); + wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n"); return -ENOMEM; } memset(rxq->rxd, 0, size); rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL); if (rxq->buf == NULL) { - wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n"); + wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n"); pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); return -ENOMEM; } @@ -1145,14 +1145,14 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); if (txq->txd == NULL) { - wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n"); + wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n"); return -ENOMEM; } memset(txq->txd, 0, size); txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL); if (txq->skb == NULL) { - wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n"); + wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n"); pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); return -ENOMEM; } @@ -1573,7 +1573,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) PCI_DMA_BIDIRECTIONAL); if (!timeout) { - wiphy_err(hw->wiphy, "command %s timeout after %u ms\n", + wiphy_err(hw->wiphy, "Command %s timeout after %u ms\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; @@ -1584,11 +1584,11 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) rc = cmd->result ? -EINVAL : 0; if (rc) - wiphy_err(hw->wiphy, "command %s error 0x%x\n", + wiphy_err(hw->wiphy, "Command %s error 0x%x\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), le16_to_cpu(cmd->result)); else if (ms > 2000) - wiphy_notice(hw->wiphy, "command %s took %d ms\n", + wiphy_notice(hw->wiphy, "Command %s took %d ms\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), ms); @@ -3210,7 +3210,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - wiphy_err(hw->wiphy, "failed to register irq handler\n"); + wiphy_err(hw->wiphy, "failed to register IRQ handler\n"); return -EIO; } @@ -3926,7 +3926,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { - wiphy_err(hw->wiphy, "cannot map device sram\n"); + wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); goto err_iounmap; } @@ -3938,7 +3938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (priv->regs == NULL) { priv->regs = pci_iomap(pdev, 2, 0x10000); if (priv->regs == NULL) { - wiphy_err(hw->wiphy, "cannot map device registers\n"); + wiphy_err(hw->wiphy, "Cannot map device registers\n"); goto err_iounmap; } } @@ -3950,14 +3950,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Ask userland hotplug daemon for the device firmware */ rc = mwl8k_request_firmware(priv); if (rc) { - wiphy_err(hw->wiphy, "firmware files not found\n"); + wiphy_err(hw->wiphy, "Firmware files not found\n"); goto err_stop_firmware; } /* Load firmware into hardware */ rc = mwl8k_load_firmware(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot start firmware\n"); + wiphy_err(hw->wiphy, "Cannot start firmware\n"); goto err_stop_firmware; } @@ -4047,7 +4047,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - wiphy_err(hw->wiphy, "failed to register irq handler\n"); + wiphy_err(hw->wiphy, "failed to register IRQ handler\n"); goto err_free_queues; } @@ -4067,7 +4067,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_get_hw_spec_sta(hw); } if (rc) { - wiphy_err(hw->wiphy, "cannot initialise firmware\n"); + wiphy_err(hw->wiphy, "Cannot initialise firmware\n"); goto err_free_irq; } @@ -4081,14 +4081,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot disable\n"); + wiphy_err(hw->wiphy, "Cannot disable\n"); goto err_free_irq; } /* Clear MAC address */ rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); if (rc) { - wiphy_err(hw->wiphy, "cannot clear mac address\n"); + wiphy_err(hw->wiphy, "Cannot clear MAC address\n"); goto err_free_irq; } @@ -4098,7 +4098,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = ieee80211_register_hw(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot register device\n"); + wiphy_err(hw->wiphy, "Cannot register device\n"); goto err_free_queues; } diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index d687cb7f2a5..78347041ec4 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -167,7 +167,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, } if (j == 0) { - wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n", + wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n", (band == IEEE80211_BAND_2GHZ) ? 2 : 5); ret = -ENODATA; @@ -695,12 +695,12 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) u8 perm_addr[ETH_ALEN]; wiphy_warn(dev->wiphy, - "invalid hwaddr! using randomly generated mac addr\n"); + "Invalid hwaddr! Using randomly generated MAC addr\n"); random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } - wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n", + wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n", dev->wiphy->perm_addr, priv->version, p54_rf_chips[priv->rxhw]); diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 47006bca485..15b20c29a60 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -125,7 +125,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) if (fw_version) wiphy_info(priv->hw->wiphy, - "fw rev %s - softmac protocol %x.%x\n", + "FW rev %s - Softmac protocol %x.%x\n", fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); if (priv->fw_var < 0x500) diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c index ea91f5cce6b..3837e1eec5f 100644 --- a/drivers/net/wireless/p54/led.c +++ b/drivers/net/wireless/p54/led.c @@ -58,7 +58,7 @@ static void p54_update_leds(struct work_struct *work) err = p54_set_leds(priv); if (err && net_ratelimit()) wiphy_err(priv->hw->wiphy, - "failed to update leds (%d).\n", err); + "failed to update LEDs (%d).\n", err); if (rerun) ieee80211_queue_delayed_work(priv->hw, &priv->led_work, @@ -103,7 +103,7 @@ static int p54_register_led(struct p54_common *priv, err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev); if (err) wiphy_err(priv->hw->wiphy, - "failed to register %s led.\n", name); + "Failed to register %s LED.\n", name); else led->registered = 1; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 822f8dc26e9..1eacba4daa5 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -466,7 +466,7 @@ static int p54p_open(struct ieee80211_hw *dev) P54P_READ(dev_int); if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - wiphy_err(dev->wiphy, "cannot boot firmware!\n"); + wiphy_err(dev->wiphy, "Cannot boot firmware!\n"); p54p_stop(dev); return -ETIMEDOUT; } diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 427b46f558e..173aec3d6e7 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -540,7 +540,7 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) case P54_TRAP_BEACON_TX: break; case P54_TRAP_RADAR: - wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq); + wiphy_info(priv->hw->wiphy, "radar (freq:%d MHz)\n", freq); break; case P54_TRAP_NO_BEACON: if (priv->vif) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index b50c39aaec0..30107ce78df 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -445,7 +445,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) &priv->rx_ring_dma); if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - wiphy_err(dev->wiphy, "cannot allocate rx ring\n"); + wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); return -ENOMEM; } @@ -502,7 +502,7 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); if (!ring || (unsigned long)ring & 0xFF) { - wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n", + wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", prio); return -ENOMEM; } @@ -568,7 +568,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) ret = request_irq(priv->pdev->irq, rtl8180_interrupt, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) { - wiphy_err(dev->wiphy, "failed to register irq handler\n"); + wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); goto err_free_rings; } diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 5738a55c1b0..98e0351c1dd 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -573,7 +573,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev) } while (--i); if (!i) { - wiphy_err(dev->wiphy, "reset timeout!\n"); + wiphy_err(dev->wiphy, "Reset timeout!\n"); return -ETIMEDOUT; } @@ -1526,7 +1526,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n", + wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", mac_addr, chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index fd96f911232..97eebdcf7eb 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c @@ -366,7 +366,7 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044d); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", rtl8225_read(dev, 6)); } @@ -735,7 +735,7 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044D); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", rtl8225_read(dev, 6)); } -- cgit v1.2.3-70-g09d2 From 6a017e043a8c5e4f1e7c1152bc6477da8066f5f6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 18 Aug 2010 12:53:28 -0700 Subject: iwlwifi: use long monitor timer for 5300 series For 5000 series of devices, use long monitor timer to check stuck tx queues. This modification apply to all the 5000 series including 5300 and others. Cc: stable@kernel.org [2.6.35] Reported-by: drago01 Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 0cbefa3d1e4..48bdcd8d2e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -663,7 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -693,7 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, -- cgit v1.2.3-70-g09d2 From a49f37eed22b74221f271811ea41323654e40dad Mon Sep 17 00:00:00 2001 From: Sachin Sanap Date: Fri, 13 Aug 2010 21:22:49 +0000 Subject: net: add Fast Ethernet driver for PXA168. Signed-off-by: Sachin Sanap Signed-off-by: David S. Miller --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/pxa168_eth.c | 1666 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pxa168_eth.h | 30 + 4 files changed, 1707 insertions(+) create mode 100644 drivers/net/pxa168_eth.c create mode 100644 include/linux/pxa168_eth.h (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ebe68395ecf..fe581566cb2 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -928,6 +928,16 @@ config SMC91X The module will be called smc91x. If you want to compile it as a module, say M here and read . +config PXA168_ETH + tristate "Marvell pxa168 ethernet support" + depends on CPU_PXA168 + select PHYLIB + help + This driver supports the pxa168 Ethernet ports. + + To compile this driver as a module, choose M here. The module + will be called pxa168_eth. + config NET_NETX tristate "NetX Ethernet support" select MII diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 56e8c27f77c..3e8f150c4b1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -244,6 +244,7 @@ obj-$(CONFIG_MYRI10GE) += myri10ge/ obj-$(CONFIG_SMC91X) += smc91x.o obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_SMSC911X) += smsc911x.o +obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o obj-$(CONFIG_BFIN_MAC) += bfin_mac.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c new file mode 100644 index 00000000000..ecc64d750cc --- /dev/null +++ b/drivers/net/pxa168_eth.c @@ -0,0 +1,1666 @@ +/* + * PXA168 ethernet driver. + * Most of the code is derived from mv643xx ethernet driver. + * + * Copyright (C) 2010 Marvell International Ltd. + * Sachin Sanap + * Philip Rakity + * Mark Brown + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pxa168-eth" +#define DRIVER_VERSION "0.3" + +/* + * Registers + */ + +#define PHY_ADDRESS 0x0000 +#define SMI 0x0010 +#define PORT_CONFIG 0x0400 +#define PORT_CONFIG_EXT 0x0408 +#define PORT_COMMAND 0x0410 +#define PORT_STATUS 0x0418 +#define HTPR 0x0428 +#define SDMA_CONFIG 0x0440 +#define SDMA_CMD 0x0448 +#define INT_CAUSE 0x0450 +#define INT_W_CLEAR 0x0454 +#define INT_MASK 0x0458 +#define ETH_F_RX_DESC_0 0x0480 +#define ETH_C_RX_DESC_0 0x04A0 +#define ETH_C_TX_DESC_1 0x04E4 + +/* smi register */ +#define SMI_BUSY (1 << 28) /* 0 - Write, 1 - Read */ +#define SMI_R_VALID (1 << 27) /* 0 - Write, 1 - Read */ +#define SMI_OP_W (0 << 26) /* Write operation */ +#define SMI_OP_R (1 << 26) /* Read operation */ + +#define PHY_WAIT_ITERATIONS 10 + +#define PXA168_ETH_PHY_ADDR_DEFAULT 0 +/* RX & TX descriptor command */ +#define BUF_OWNED_BY_DMA (1 << 31) + +/* RX descriptor status */ +#define RX_EN_INT (1 << 23) +#define RX_FIRST_DESC (1 << 17) +#define RX_LAST_DESC (1 << 16) +#define RX_ERROR (1 << 15) + +/* TX descriptor command */ +#define TX_EN_INT (1 << 23) +#define TX_GEN_CRC (1 << 22) +#define TX_ZERO_PADDING (1 << 18) +#define TX_FIRST_DESC (1 << 17) +#define TX_LAST_DESC (1 << 16) +#define TX_ERROR (1 << 15) + +/* SDMA_CMD */ +#define SDMA_CMD_AT (1 << 31) +#define SDMA_CMD_TXDL (1 << 24) +#define SDMA_CMD_TXDH (1 << 23) +#define SDMA_CMD_AR (1 << 15) +#define SDMA_CMD_ERD (1 << 7) + +/* Bit definitions of the Port Config Reg */ +#define PCR_HS (1 << 12) +#define PCR_EN (1 << 7) +#define PCR_PM (1 << 0) + +/* Bit definitions of the Port Config Extend Reg */ +#define PCXR_2BSM (1 << 28) +#define PCXR_DSCP_EN (1 << 21) +#define PCXR_MFL_1518 (0 << 14) +#define PCXR_MFL_1536 (1 << 14) +#define PCXR_MFL_2048 (2 << 14) +#define PCXR_MFL_64K (3 << 14) +#define PCXR_FLP (1 << 11) +#define PCXR_PRIO_TX_OFF 3 +#define PCXR_TX_HIGH_PRI (7 << PCXR_PRIO_TX_OFF) + +/* Bit definitions of the SDMA Config Reg */ +#define SDCR_BSZ_OFF 12 +#define SDCR_BSZ8 (3 << SDCR_BSZ_OFF) +#define SDCR_BSZ4 (2 << SDCR_BSZ_OFF) +#define SDCR_BSZ2 (1 << SDCR_BSZ_OFF) +#define SDCR_BSZ1 (0 << SDCR_BSZ_OFF) +#define SDCR_BLMR (1 << 6) +#define SDCR_BLMT (1 << 7) +#define SDCR_RIFB (1 << 9) +#define SDCR_RC_OFF 2 +#define SDCR_RC_MAX_RETRANS (0xf << SDCR_RC_OFF) + +/* + * Bit definitions of the Interrupt Cause Reg + * and Interrupt MASK Reg is the same + */ +#define ICR_RXBUF (1 << 0) +#define ICR_TXBUF_H (1 << 2) +#define ICR_TXBUF_L (1 << 3) +#define ICR_TXEND_H (1 << 6) +#define ICR_TXEND_L (1 << 7) +#define ICR_RXERR (1 << 8) +#define ICR_TXERR_H (1 << 10) +#define ICR_TXERR_L (1 << 11) +#define ICR_TX_UDR (1 << 13) +#define ICR_MII_CH (1 << 28) + +#define ALL_INTS (ICR_TXBUF_H | ICR_TXBUF_L | ICR_TX_UDR |\ + ICR_TXERR_H | ICR_TXERR_L |\ + ICR_TXEND_H | ICR_TXEND_L |\ + ICR_RXBUF | ICR_RXERR | ICR_MII_CH) + +#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ + +#define NUM_RX_DESCS 64 +#define NUM_TX_DESCS 64 + +#define HASH_ADD 0 +#define HASH_DELETE 1 +#define HASH_ADDR_TABLE_SIZE 0x4000 /* 16K (1/2K address - PCR_HS == 1) */ +#define HOP_NUMBER 12 + +/* Bit definitions for Port status */ +#define PORT_SPEED_100 (1 << 0) +#define FULL_DUPLEX (1 << 1) +#define FLOW_CONTROL_ENABLED (1 << 2) +#define LINK_UP (1 << 3) + +/* Bit definitions for work to be done */ +#define WORK_LINK (1 << 0) +#define WORK_TX_DONE (1 << 1) + +/* + * Misc definitions. + */ +#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) + +struct rx_desc { + u32 cmd_sts; /* Descriptor command status */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u16 buf_size; /* Buffer size */ + u32 buf_ptr; /* Descriptor buffer pointer */ + u32 next_desc_ptr; /* Next descriptor pointer */ +}; + +struct tx_desc { + u32 cmd_sts; /* Command/status field */ + u16 reserved; + u16 byte_cnt; /* buffer byte count */ + u32 buf_ptr; /* pointer to buffer for this descriptor */ + u32 next_desc_ptr; /* Pointer to next descriptor */ +}; + +struct pxa168_eth_private { + int port_num; /* User Ethernet port number */ + + int rx_resource_err; /* Rx ring resource error flag */ + + /* Next available and first returning Rx resource */ + int rx_curr_desc_q, rx_used_desc_q; + + /* Next available and first returning Tx resource */ + int tx_curr_desc_q, tx_used_desc_q; + + struct rx_desc *p_rx_desc_area; + dma_addr_t rx_desc_dma; + int rx_desc_area_size; + struct sk_buff **rx_skb; + + struct tx_desc *p_tx_desc_area; + dma_addr_t tx_desc_dma; + int tx_desc_area_size; + struct sk_buff **tx_skb; + + struct work_struct tx_timeout_task; + + struct net_device *dev; + struct napi_struct napi; + u8 work_todo; + int skb_size; + + struct net_device_stats stats; + /* Size of Tx Ring per queue */ + int tx_ring_size; + /* Number of tx descriptors in use */ + int tx_desc_count; + /* Size of Rx Ring per queue */ + int rx_ring_size; + /* Number of rx descriptors in use */ + int rx_desc_count; + + /* + * Used in case RX Ring is empty, which can occur when + * system does not have resources (skb's) + */ + struct timer_list timeout; + struct mii_bus *smi_bus; + struct phy_device *phy; + + /* clock */ + struct clk *clk; + struct pxa168_eth_platform_data *pd; + /* + * Ethernet controller base address. + */ + void __iomem *base; + + /* Pointer to the hardware address filter table */ + void *htpr; + dma_addr_t htpr_dma; +}; + +struct addr_table_entry { + __le32 lo; + __le32 hi; +}; + +/* Bit fields of a Hash Table Entry */ +enum hash_table_entry { + HASH_ENTRY_VALID = 1, + SKIP = 2, + HASH_ENTRY_RECEIVE_DISCARD = 4, + HASH_ENTRY_RECEIVE_DISCARD_BIT = 2 +}; + +static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static int pxa168_init_hw(struct pxa168_eth_private *pep); +static void eth_port_reset(struct net_device *dev); +static void eth_port_start(struct net_device *dev); +static int pxa168_eth_open(struct net_device *dev); +static int pxa168_eth_stop(struct net_device *dev); +static int ethernet_phy_setup(struct net_device *dev); + +static inline u32 rdl(struct pxa168_eth_private *pep, int offset) +{ + return readl(pep->base + offset); +} + +static inline void wrl(struct pxa168_eth_private *pep, int offset, u32 data) +{ + writel(data, pep->base + offset); +} + +static void abort_dma(struct pxa168_eth_private *pep) +{ + int delay; + int max_retries = 40; + + do { + wrl(pep, SDMA_CMD, SDMA_CMD_AR | SDMA_CMD_AT); + udelay(100); + + delay = 10; + while ((rdl(pep, SDMA_CMD) & (SDMA_CMD_AR | SDMA_CMD_AT)) + && delay-- > 0) { + udelay(10); + } + } while (max_retries-- > 0 && delay <= 0); + + if (max_retries <= 0) + printk(KERN_ERR "%s : DMA Stuck\n", __func__); +} + +static int ethernet_phy_get(struct pxa168_eth_private *pep) +{ + unsigned int reg_data; + + reg_data = rdl(pep, PHY_ADDRESS); + + return (reg_data >> (5 * pep->port_num)) & 0x1f; +} + +static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr) +{ + u32 reg_data; + int addr_shift = 5 * pep->port_num; + + reg_data = rdl(pep, PHY_ADDRESS); + reg_data &= ~(0x1f << addr_shift); + reg_data |= (phy_addr & 0x1f) << addr_shift; + wrl(pep, PHY_ADDRESS, reg_data); +} + +static void ethernet_phy_reset(struct pxa168_eth_private *pep) +{ + int data; + + data = phy_read(pep->phy, MII_BMCR); + if (data < 0) + return; + + data |= BMCR_RESET; + if (phy_write(pep->phy, MII_BMCR, data) < 0) + return; + + do { + data = phy_read(pep->phy, MII_BMCR); + } while (data >= 0 && data & BMCR_RESET); +} + +static void rxq_refill(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct sk_buff *skb; + struct rx_desc *p_used_rx_desc; + int used_rx_desc; + + while (pep->rx_desc_count < pep->rx_ring_size) { + int size; + + skb = dev_alloc_skb(pep->skb_size); + if (!skb) + break; + if (SKB_DMA_REALIGN) + skb_reserve(skb, SKB_DMA_REALIGN); + pep->rx_desc_count++; + /* Get 'used' Rx descriptor */ + used_rx_desc = pep->rx_used_desc_q; + p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc]; + size = skb->end - skb->data; + p_used_rx_desc->buf_ptr = dma_map_single(NULL, + skb->data, + size, + DMA_FROM_DEVICE); + p_used_rx_desc->buf_size = size; + pep->rx_skb[used_rx_desc] = skb; + + /* Return the descriptor to DMA ownership */ + wmb(); + p_used_rx_desc->cmd_sts = BUF_OWNED_BY_DMA | RX_EN_INT; + wmb(); + + /* Move the used descriptor pointer to the next descriptor */ + pep->rx_used_desc_q = (used_rx_desc + 1) % pep->rx_ring_size; + + /* Any Rx return cancels the Rx resource error status */ + pep->rx_resource_err = 0; + + skb_reserve(skb, ETH_HW_IP_ALIGN); + } + + /* + * If RX ring is empty of SKB, set a timer to try allocating + * again at a later time. + */ + if (pep->rx_desc_count == 0) { + pep->timeout.expires = jiffies + (HZ / 10); + add_timer(&pep->timeout); + } +} + +static inline void rxq_refill_timer_wrapper(unsigned long data) +{ + struct pxa168_eth_private *pep = (void *)data; + napi_schedule(&pep->napi); +} + +static inline u8 flip_8_bits(u8 x) +{ + return (((x) & 0x01) << 3) | (((x) & 0x02) << 1) + | (((x) & 0x04) >> 1) | (((x) & 0x08) >> 3) + | (((x) & 0x10) << 3) | (((x) & 0x20) << 1) + | (((x) & 0x40) >> 1) | (((x) & 0x80) >> 3); +} + +static void nibble_swap_every_byte(unsigned char *mac_addr) +{ + int i; + for (i = 0; i < ETH_ALEN; i++) { + mac_addr[i] = ((mac_addr[i] & 0x0f) << 4) | + ((mac_addr[i] & 0xf0) >> 4); + } +} + +static void inverse_every_nibble(unsigned char *mac_addr) +{ + int i; + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = flip_8_bits(mac_addr[i]); +} + +/* + * ---------------------------------------------------------------------------- + * This function will calculate the hash function of the address. + * Inputs + * mac_addr_orig - MAC address. + * Outputs + * return the calculated entry. + */ +static u32 hash_function(unsigned char *mac_addr_orig) +{ + u32 hash_result; + u32 addr0; + u32 addr1; + u32 addr2; + u32 addr3; + unsigned char mac_addr[ETH_ALEN]; + + /* Make a copy of MAC address since we are going to performe bit + * operations on it + */ + memcpy(mac_addr, mac_addr_orig, ETH_ALEN); + + nibble_swap_every_byte(mac_addr); + inverse_every_nibble(mac_addr); + + addr0 = (mac_addr[5] >> 2) & 0x3f; + addr1 = (mac_addr[5] & 0x03) | (((mac_addr[4] & 0x7f)) << 2); + addr2 = ((mac_addr[4] & 0x80) >> 7) | mac_addr[3] << 1; + addr3 = (mac_addr[2] & 0xff) | ((mac_addr[1] & 1) << 8); + + hash_result = (addr0 << 9) | (addr1 ^ addr2 ^ addr3); + hash_result = hash_result & 0x07ff; + return hash_result; +} + +/* + * ---------------------------------------------------------------------------- + * This function will add/del an entry to the address table. + * Inputs + * pep - ETHERNET . + * mac_addr - MAC address. + * skip - if 1, skip this address.Used in case of deleting an entry which is a + * part of chain in the hash table.We cant just delete the entry since + * that will break the chain.We need to defragment the tables time to + * time. + * rd - 0 Discard packet upon match. + * - 1 Receive packet upon match. + * Outputs + * address table entry is added/deleted. + * 0 if success. + * -ENOSPC if table full + */ +static int add_del_hash_entry(struct pxa168_eth_private *pep, + unsigned char *mac_addr, + u32 rd, u32 skip, int del) +{ + struct addr_table_entry *entry, *start; + u32 new_high; + u32 new_low; + u32 i; + + new_low = (((mac_addr[1] >> 4) & 0xf) << 15) + | (((mac_addr[1] >> 0) & 0xf) << 11) + | (((mac_addr[0] >> 4) & 0xf) << 7) + | (((mac_addr[0] >> 0) & 0xf) << 3) + | (((mac_addr[3] >> 4) & 0x1) << 31) + | (((mac_addr[3] >> 0) & 0xf) << 27) + | (((mac_addr[2] >> 4) & 0xf) << 23) + | (((mac_addr[2] >> 0) & 0xf) << 19) + | (skip << SKIP) | (rd << HASH_ENTRY_RECEIVE_DISCARD_BIT) + | HASH_ENTRY_VALID; + + new_high = (((mac_addr[5] >> 4) & 0xf) << 15) + | (((mac_addr[5] >> 0) & 0xf) << 11) + | (((mac_addr[4] >> 4) & 0xf) << 7) + | (((mac_addr[4] >> 0) & 0xf) << 3) + | (((mac_addr[3] >> 5) & 0x7) << 0); + + /* + * Pick the appropriate table, start scanning for free/reusable + * entries at the index obtained by hashing the specified MAC address + */ + start = (struct addr_table_entry *)(pep->htpr); + entry = start + hash_function(mac_addr); + for (i = 0; i < HOP_NUMBER; i++) { + if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) { + break; + } else { + /* if same address put in same position */ + if (((le32_to_cpu(entry->lo) & 0xfffffff8) == + (new_low & 0xfffffff8)) && + (le32_to_cpu(entry->hi) == new_high)) { + break; + } + } + if (entry == start + 0x7ff) + entry = start; + else + entry++; + } + + if (((le32_to_cpu(entry->lo) & 0xfffffff8) != (new_low & 0xfffffff8)) && + (le32_to_cpu(entry->hi) != new_high) && del) + return 0; + + if (i == HOP_NUMBER) { + if (!del) { + printk(KERN_INFO "%s: table section is full, need to " + "move to 16kB implementation?\n", + __FILE__); + return -ENOSPC; + } else + return 0; + } + + /* + * Update the selected entry + */ + if (del) { + entry->hi = 0; + entry->lo = 0; + } else { + entry->hi = cpu_to_le32(new_high); + entry->lo = cpu_to_le32(new_low); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * Create an addressTable entry from MAC address info + * found in the specifed net_device struct + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + */ +static void update_hash_table_mac_address(struct pxa168_eth_private *pep, + unsigned char *oaddr, + unsigned char *addr) +{ + /* Delete old entry */ + if (oaddr) + add_del_hash_entry(pep, oaddr, 1, 0, HASH_DELETE); + /* Add new entry */ + add_del_hash_entry(pep, addr, 1, 0, HASH_ADD); +} + +static int init_hash_table(struct pxa168_eth_private *pep) +{ + /* + * Hardware expects CPU to build a hash table based on a predefined + * hash function and populate it based on hardware address. The + * location of the hash table is identified by 32-bit pointer stored + * in HTPR internal register. Two possible sizes exists for the hash + * table 8kB (256kB of DRAM required (4 x 64 kB banks)) and 1/2kB + * (16kB of DRAM required (4 x 4 kB banks)).We currently only support + * 1/2kB. + */ + /* TODO: Add support for 8kB hash table and alternative hash + * function.Driver can dynamically switch to them if the 1/2kB hash + * table is full. + */ + if (pep->htpr == NULL) { + pep->htpr = dma_alloc_coherent(pep->dev->dev.parent, + HASH_ADDR_TABLE_SIZE, + &pep->htpr_dma, GFP_KERNEL); + if (pep->htpr == NULL) + return -ENOMEM; + } + memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE); + wrl(pep, HTPR, pep->htpr_dma); + return 0; +} + +static void pxa168_eth_set_rx_mode(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct netdev_hw_addr *ha; + u32 val; + + val = rdl(pep, PORT_CONFIG); + if (dev->flags & IFF_PROMISC) + val |= PCR_PM; + else + val &= ~PCR_PM; + wrl(pep, PORT_CONFIG, val); + + /* + * Remove the old list of MAC address and add dev->addr + * and multicast address. + */ + memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE); + update_hash_table_mac_address(pep, NULL, dev->dev_addr); + + netdev_for_each_mc_addr(ha, dev) + update_hash_table_mac_address(pep, NULL, ha->addr); +} + +static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sa = addr; + struct pxa168_eth_private *pep = netdev_priv(dev); + unsigned char oldMac[ETH_ALEN]; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EINVAL; + memcpy(oldMac, dev->dev_addr, ETH_ALEN); + memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); + netif_addr_lock_bh(dev); + update_hash_table_mac_address(pep, oldMac, dev->dev_addr); + netif_addr_unlock_bh(dev); + return 0; +} + +static void eth_port_start(struct net_device *dev) +{ + unsigned int val = 0; + struct pxa168_eth_private *pep = netdev_priv(dev); + int tx_curr_desc, rx_curr_desc; + + /* Perform PHY reset, if there is a PHY. */ + if (pep->phy != NULL) { + struct ethtool_cmd cmd; + + pxa168_get_settings(pep->dev, &cmd); + ethernet_phy_reset(pep); + pxa168_set_settings(pep->dev, &cmd); + } + + /* Assignment of Tx CTRP of given queue */ + tx_curr_desc = pep->tx_curr_desc_q; + wrl(pep, ETH_C_TX_DESC_1, + (u32) ((struct tx_desc *)pep->tx_desc_dma + tx_curr_desc)); + + /* Assignment of Rx CRDP of given queue */ + rx_curr_desc = pep->rx_curr_desc_q; + wrl(pep, ETH_C_RX_DESC_0, + (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); + + wrl(pep, ETH_F_RX_DESC_0, + (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); + + /* Clear all interrupts */ + wrl(pep, INT_CAUSE, 0); + + /* Enable all interrupts for receive, transmit and error. */ + wrl(pep, INT_MASK, ALL_INTS); + + val = rdl(pep, PORT_CONFIG); + val |= PCR_EN; + wrl(pep, PORT_CONFIG, val); + + /* Start RX DMA engine */ + val = rdl(pep, SDMA_CMD); + val |= SDMA_CMD_ERD; + wrl(pep, SDMA_CMD, val); +} + +static void eth_port_reset(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + unsigned int val = 0; + + /* Stop all interrupts for receive, transmit and error. */ + wrl(pep, INT_MASK, 0); + + /* Clear all interrupts */ + wrl(pep, INT_CAUSE, 0); + + /* Stop RX DMA */ + val = rdl(pep, SDMA_CMD); + val &= ~SDMA_CMD_ERD; /* abort dma command */ + + /* Abort any transmit and receive operations and put DMA + * in idle state. + */ + abort_dma(pep); + + /* Disable port */ + val = rdl(pep, PORT_CONFIG); + val &= ~PCR_EN; + wrl(pep, PORT_CONFIG, val); +} + +/* + * txq_reclaim - Free the tx desc data for completed descriptors + * If force is non-zero, frees uncompleted descriptors as well + */ +static int txq_reclaim(struct net_device *dev, int force) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct tx_desc *desc; + u32 cmd_sts; + struct sk_buff *skb; + int tx_index; + dma_addr_t addr; + int count; + int released = 0; + + netif_tx_lock(dev); + + pep->work_todo &= ~WORK_TX_DONE; + while (pep->tx_desc_count > 0) { + tx_index = pep->tx_used_desc_q; + desc = &pep->p_tx_desc_area[tx_index]; + cmd_sts = desc->cmd_sts; + if (!force && (cmd_sts & BUF_OWNED_BY_DMA)) { + if (released > 0) { + goto txq_reclaim_end; + } else { + released = -1; + goto txq_reclaim_end; + } + } + pep->tx_used_desc_q = (tx_index + 1) % pep->tx_ring_size; + pep->tx_desc_count--; + addr = desc->buf_ptr; + count = desc->byte_cnt; + skb = pep->tx_skb[tx_index]; + if (skb) + pep->tx_skb[tx_index] = NULL; + + if (cmd_sts & TX_ERROR) { + if (net_ratelimit()) + printk(KERN_ERR "%s: Error in TX\n", dev->name); + dev->stats.tx_errors++; + } + dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); + if (skb) + dev_kfree_skb_irq(skb); + released++; + } +txq_reclaim_end: + netif_tx_unlock(dev); + return released; +} + +static void pxa168_eth_tx_timeout(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + printk(KERN_INFO "%s: TX timeout desc_count %d\n", + dev->name, pep->tx_desc_count); + + schedule_work(&pep->tx_timeout_task); +} + +static void pxa168_eth_tx_timeout_task(struct work_struct *work) +{ + struct pxa168_eth_private *pep = container_of(work, + struct pxa168_eth_private, + tx_timeout_task); + struct net_device *dev = pep->dev; + pxa168_eth_stop(dev); + pxa168_eth_open(dev); +} + +static int rxq_process(struct net_device *dev, int budget) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + unsigned int received_packets = 0; + struct sk_buff *skb; + + while (budget-- > 0) { + int rx_next_curr_desc, rx_curr_desc, rx_used_desc; + struct rx_desc *rx_desc; + unsigned int cmd_sts; + + /* Do not process Rx ring in case of Rx ring resource error */ + if (pep->rx_resource_err) + break; + rx_curr_desc = pep->rx_curr_desc_q; + rx_used_desc = pep->rx_used_desc_q; + rx_desc = &pep->p_rx_desc_area[rx_curr_desc]; + cmd_sts = rx_desc->cmd_sts; + rmb(); + if (cmd_sts & (BUF_OWNED_BY_DMA)) + break; + skb = pep->rx_skb[rx_curr_desc]; + pep->rx_skb[rx_curr_desc] = NULL; + + rx_next_curr_desc = (rx_curr_desc + 1) % pep->rx_ring_size; + pep->rx_curr_desc_q = rx_next_curr_desc; + + /* Rx descriptors exhausted. */ + /* Set the Rx ring resource error flag */ + if (rx_next_curr_desc == rx_used_desc) + pep->rx_resource_err = 1; + pep->rx_desc_count--; + dma_unmap_single(NULL, rx_desc->buf_ptr, + rx_desc->buf_size, + DMA_FROM_DEVICE); + received_packets++; + /* + * Update statistics. + * Note byte count includes 4 byte CRC count + */ + stats->rx_packets++; + stats->rx_bytes += rx_desc->byte_cnt; + /* + * In case received a packet without first / last bits on OR + * the error summary bit is on, the packets needs to be droped. + */ + if (((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) != + (RX_FIRST_DESC | RX_LAST_DESC)) + || (cmd_sts & RX_ERROR)) { + + stats->rx_dropped++; + if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) != + (RX_FIRST_DESC | RX_LAST_DESC)) { + if (net_ratelimit()) + printk(KERN_ERR + "%s: Rx pkt on multiple desc\n", + dev->name); + } + if (cmd_sts & RX_ERROR) + stats->rx_errors++; + dev_kfree_skb_irq(skb); + } else { + /* + * The -4 is for the CRC in the trailer of the + * received packet + */ + skb_put(skb, rx_desc->byte_cnt - 4); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + } + dev->last_rx = jiffies; + } + /* Fill RX ring with skb's */ + rxq_refill(dev); + return received_packets; +} + +static int pxa168_eth_collect_events(struct pxa168_eth_private *pep, + struct net_device *dev) +{ + u32 icr; + int ret = 0; + + icr = rdl(pep, INT_CAUSE); + if (icr == 0) + return IRQ_NONE; + + wrl(pep, INT_CAUSE, ~icr); + if (icr & (ICR_TXBUF_H | ICR_TXBUF_L)) { + pep->work_todo |= WORK_TX_DONE; + ret = 1; + } + if (icr & ICR_RXBUF) + ret = 1; + if (icr & ICR_MII_CH) { + pep->work_todo |= WORK_LINK; + ret = 1; + } + return ret; +} + +static void handle_link_event(struct pxa168_eth_private *pep) +{ + struct net_device *dev = pep->dev; + u32 port_status; + int speed; + int duplex; + int fc; + + port_status = rdl(pep, PORT_STATUS); + if (!(port_status & LINK_UP)) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link down\n", dev->name); + netif_carrier_off(dev); + txq_reclaim(dev, 1); + } + return; + } + if (port_status & PORT_SPEED_100) + speed = 100; + else + speed = 10; + + duplex = (port_status & FULL_DUPLEX) ? 1 : 0; + fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0; + printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " + "flow control %sabled\n", dev->name, + speed, duplex ? "full" : "half", fc ? "en" : "dis"); + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); +} + +static irqreturn_t pxa168_eth_int_handler(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (unlikely(!pxa168_eth_collect_events(pep, dev))) + return IRQ_NONE; + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + napi_schedule(&pep->napi); + return IRQ_HANDLED; +} + +static void pxa168_eth_recalc_skb_size(struct pxa168_eth_private *pep) +{ + int skb_size; + + /* + * Reserve 2+14 bytes for an ethernet header (the hardware + * automatically prepends 2 bytes of dummy data to each + * received packet), 16 bytes for up to four VLAN tags, and + * 4 bytes for the trailing FCS -- 36 bytes total. + */ + skb_size = pep->dev->mtu + 36; + + /* + * Make sure that the skb size is a multiple of 8 bytes, as + * the lower three bits of the receive descriptor's buffer + * size field are ignored by the hardware. + */ + pep->skb_size = (skb_size + 7) & ~7; + + /* + * If NET_SKB_PAD is smaller than a cache line, + * netdev_alloc_skb() will cause skb->data to be misaligned + * to a cache line boundary. If this is the case, include + * some extra space to allow re-aligning the data area. + */ + pep->skb_size += SKB_DMA_REALIGN; + +} + +static int set_port_config_ext(struct pxa168_eth_private *pep) +{ + int skb_size; + + pxa168_eth_recalc_skb_size(pep); + if (pep->skb_size <= 1518) + skb_size = PCXR_MFL_1518; + else if (pep->skb_size <= 1536) + skb_size = PCXR_MFL_1536; + else if (pep->skb_size <= 2048) + skb_size = PCXR_MFL_2048; + else + skb_size = PCXR_MFL_64K; + + /* Extended Port Configuration */ + wrl(pep, + PORT_CONFIG_EXT, PCXR_2BSM | /* Two byte prefix aligns IP hdr */ + PCXR_DSCP_EN | /* Enable DSCP in IP */ + skb_size | PCXR_FLP | /* do not force link pass */ + PCXR_TX_HIGH_PRI); /* Transmit - high priority queue */ + + return 0; +} + +static int pxa168_init_hw(struct pxa168_eth_private *pep) +{ + int err = 0; + + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + wrl(pep, INT_CAUSE, 0); + /* Write to ICR to clear interrupts. */ + wrl(pep, INT_W_CLEAR, 0); + /* Abort any transmit and receive operations and put DMA + * in idle state. + */ + abort_dma(pep); + /* Initialize address hash table */ + err = init_hash_table(pep); + if (err) + return err; + /* SDMA configuration */ + wrl(pep, SDMA_CONFIG, SDCR_BSZ8 | /* Burst size = 32 bytes */ + SDCR_RIFB | /* Rx interrupt on frame */ + SDCR_BLMT | /* Little endian transmit */ + SDCR_BLMR | /* Little endian receive */ + SDCR_RC_MAX_RETRANS); /* Max retransmit count */ + /* Port Configuration */ + wrl(pep, PORT_CONFIG, PCR_HS); /* Hash size is 1/2kb */ + set_port_config_ext(pep); + + return err; +} + +static int rxq_init(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct rx_desc *p_rx_desc; + int size = 0, i = 0; + int rx_desc_num = pep->rx_ring_size; + + /* Allocate RX skb rings */ + pep->rx_skb = kmalloc(sizeof(*pep->rx_skb) * pep->rx_ring_size, + GFP_KERNEL); + if (!pep->rx_skb) { + printk(KERN_ERR "%s: Cannot alloc RX skb ring\n", dev->name); + return -ENOMEM; + } + /* Allocate RX ring */ + pep->rx_desc_count = 0; + size = pep->rx_ring_size * sizeof(struct rx_desc); + pep->rx_desc_area_size = size; + pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->rx_desc_dma, GFP_KERNEL); + if (!pep->p_rx_desc_area) { + printk(KERN_ERR "%s: Cannot alloc RX ring (size %d bytes)\n", + dev->name, size); + goto out; + } + memset((void *)pep->p_rx_desc_area, 0, size); + /* initialize the next_desc_ptr links in the Rx descriptors ring */ + p_rx_desc = (struct rx_desc *)pep->p_rx_desc_area; + for (i = 0; i < rx_desc_num; i++) { + p_rx_desc[i].next_desc_ptr = pep->rx_desc_dma + + ((i + 1) % rx_desc_num) * sizeof(struct rx_desc); + } + /* Save Rx desc pointer to driver struct. */ + pep->rx_curr_desc_q = 0; + pep->rx_used_desc_q = 0; + pep->rx_desc_area_size = rx_desc_num * sizeof(struct rx_desc); + return 0; +out: + kfree(pep->rx_skb); + return -ENOMEM; +} + +static void rxq_deinit(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int curr; + + /* Free preallocated skb's on RX rings */ + for (curr = 0; pep->rx_desc_count && curr < pep->rx_ring_size; curr++) { + if (pep->rx_skb[curr]) { + dev_kfree_skb(pep->rx_skb[curr]); + pep->rx_desc_count--; + } + } + if (pep->rx_desc_count) + printk(KERN_ERR + "Error in freeing Rx Ring. %d skb's still\n", + pep->rx_desc_count); + /* Free RX ring */ + if (pep->p_rx_desc_area) + dma_free_coherent(pep->dev->dev.parent, pep->rx_desc_area_size, + pep->p_rx_desc_area, pep->rx_desc_dma); + kfree(pep->rx_skb); +} + +static int txq_init(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct tx_desc *p_tx_desc; + int size = 0, i = 0; + int tx_desc_num = pep->tx_ring_size; + + pep->tx_skb = kmalloc(sizeof(*pep->tx_skb) * pep->tx_ring_size, + GFP_KERNEL); + if (!pep->tx_skb) { + printk(KERN_ERR "%s: Cannot alloc TX skb ring\n", dev->name); + return -ENOMEM; + } + /* Allocate TX ring */ + pep->tx_desc_count = 0; + size = pep->tx_ring_size * sizeof(struct tx_desc); + pep->tx_desc_area_size = size; + pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->tx_desc_dma, GFP_KERNEL); + if (!pep->p_tx_desc_area) { + printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n", + dev->name, size); + goto out; + } + memset((void *)pep->p_tx_desc_area, 0, pep->tx_desc_area_size); + /* Initialize the next_desc_ptr links in the Tx descriptors ring */ + p_tx_desc = (struct tx_desc *)pep->p_tx_desc_area; + for (i = 0; i < tx_desc_num; i++) { + p_tx_desc[i].next_desc_ptr = pep->tx_desc_dma + + ((i + 1) % tx_desc_num) * sizeof(struct tx_desc); + } + pep->tx_curr_desc_q = 0; + pep->tx_used_desc_q = 0; + pep->tx_desc_area_size = tx_desc_num * sizeof(struct tx_desc); + return 0; +out: + kfree(pep->tx_skb); + return -ENOMEM; +} + +static void txq_deinit(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + /* Free outstanding skb's on TX ring */ + txq_reclaim(dev, 1); + BUG_ON(pep->tx_used_desc_q != pep->tx_curr_desc_q); + /* Free TX ring */ + if (pep->p_tx_desc_area) + dma_free_coherent(pep->dev->dev.parent, pep->tx_desc_area_size, + pep->p_tx_desc_area, pep->tx_desc_dma); + kfree(pep->tx_skb); +} + +static int pxa168_eth_open(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int err; + + err = request_irq(dev->irq, pxa168_eth_int_handler, + IRQF_DISABLED, dev->name, dev); + if (err) { + dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n"); + return -EAGAIN; + } + pep->rx_resource_err = 0; + err = rxq_init(dev); + if (err != 0) + goto out_free_irq; + err = txq_init(dev); + if (err != 0) + goto out_free_rx_skb; + pep->rx_used_desc_q = 0; + pep->rx_curr_desc_q = 0; + + /* Fill RX ring with skb's */ + rxq_refill(dev); + pep->rx_used_desc_q = 0; + pep->rx_curr_desc_q = 0; + netif_carrier_off(dev); + eth_port_start(dev); + napi_enable(&pep->napi); + return 0; +out_free_rx_skb: + rxq_deinit(dev); +out_free_irq: + free_irq(dev->irq, dev); + return err; +} + +static int pxa168_eth_stop(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + eth_port_reset(dev); + + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + wrl(pep, INT_CAUSE, 0); + /* Write to ICR to clear interrupts. */ + wrl(pep, INT_W_CLEAR, 0); + napi_disable(&pep->napi); + del_timer_sync(&pep->timeout); + netif_carrier_off(dev); + free_irq(dev->irq, dev); + rxq_deinit(dev); + txq_deinit(dev); + + return 0; +} + +static int pxa168_eth_change_mtu(struct net_device *dev, int mtu) +{ + int retval; + struct pxa168_eth_private *pep = netdev_priv(dev); + + if ((mtu > 9500) || (mtu < 68)) + return -EINVAL; + + dev->mtu = mtu; + retval = set_port_config_ext(pep); + + if (!netif_running(dev)) + return 0; + + /* + * Stop and then re-open the interface. This will allocate RX + * skbs of the new MTU. + * There is a possible danger that the open will not succeed, + * due to memory being full. + */ + pxa168_eth_stop(dev); + if (pxa168_eth_open(dev)) { + dev_printk(KERN_ERR, &dev->dev, + "fatal error on re-opening device after " + "MTU change\n"); + } + + return 0; +} + +static int eth_alloc_tx_desc_index(struct pxa168_eth_private *pep) +{ + int tx_desc_curr; + + tx_desc_curr = pep->tx_curr_desc_q; + pep->tx_curr_desc_q = (tx_desc_curr + 1) % pep->tx_ring_size; + BUG_ON(pep->tx_curr_desc_q == pep->tx_used_desc_q); + pep->tx_desc_count++; + + return tx_desc_curr; +} + +static int pxa168_rx_poll(struct napi_struct *napi, int budget) +{ + struct pxa168_eth_private *pep = + container_of(napi, struct pxa168_eth_private, napi); + struct net_device *dev = pep->dev; + int work_done = 0; + + if (unlikely(pep->work_todo & WORK_LINK)) { + pep->work_todo &= ~(WORK_LINK); + handle_link_event(pep); + } + /* + * We call txq_reclaim every time since in NAPI interupts are disabled + * and due to this we miss the TX_DONE interrupt,which is not updated in + * interrupt status register. + */ + txq_reclaim(dev, 0); + if (netif_queue_stopped(dev) + && pep->tx_ring_size - pep->tx_desc_count > 1) { + netif_wake_queue(dev); + } + work_done = rxq_process(dev, budget); + if (work_done < budget) { + napi_complete(napi); + wrl(pep, INT_MASK, ALL_INTS); + } + + return work_done; +} + +static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct tx_desc *desc; + int tx_index; + int length; + + tx_index = eth_alloc_tx_desc_index(pep); + desc = &pep->p_tx_desc_area[tx_index]; + length = skb->len; + pep->tx_skb[tx_index] = skb; + desc->byte_cnt = length; + desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + wmb(); + desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC | + TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT; + wmb(); + wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD); + + stats->tx_bytes += skb->len; + stats->tx_packets++; + dev->trans_start = jiffies; + if (pep->tx_ring_size - pep->tx_desc_count <= 1) { + /* We handled the current skb, but now we are out of space.*/ + netif_stop_queue(dev); + } + + return NETDEV_TX_OK; +} + +static int smi_wait_ready(struct pxa168_eth_private *pep) +{ + int i = 0; + + /* wait for the SMI register to become available */ + for (i = 0; rdl(pep, SMI) & SMI_BUSY; i++) { + if (i == PHY_WAIT_ITERATIONS) + return -ETIMEDOUT; + msleep(10); + } + + return 0; +} + +static int pxa168_smi_read(struct mii_bus *bus, int phy_addr, int regnum) +{ + struct pxa168_eth_private *pep = bus->priv; + int i = 0; + int val; + + if (smi_wait_ready(pep)) { + printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) | SMI_OP_R); + /* now wait for the data to be valid */ + for (i = 0; !((val = rdl(pep, SMI)) & SMI_R_VALID); i++) { + if (i == PHY_WAIT_ITERATIONS) { + printk(KERN_WARNING + "pxa168_eth: SMI bus read not valid\n"); + return -ENODEV; + } + msleep(10); + } + + return val & 0xffff; +} + +static int pxa168_smi_write(struct mii_bus *bus, int phy_addr, int regnum, + u16 value) +{ + struct pxa168_eth_private *pep = bus->priv; + + if (smi_wait_ready(pep)) { + printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + + wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) | + SMI_OP_W | (value & 0xffff)); + + if (smi_wait_ready(pep)) { + printk(KERN_ERR "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, + int cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + if (pep->phy != NULL) + return phy_mii_ioctl(pep->phy, if_mii(ifr), cmd); + + return -EOPNOTSUPP; +} + +static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr) +{ + struct mii_bus *bus = pep->smi_bus; + struct phy_device *phydev; + int start; + int num; + int i; + + if (phy_addr == PXA168_ETH_PHY_ADDR_DEFAULT) { + /* Scan entire range */ + start = ethernet_phy_get(pep); + num = 32; + } else { + /* Use phy addr specific to platform */ + start = phy_addr & 0x1f; + num = 1; + } + phydev = NULL; + for (i = 0; i < num; i++) { + int addr = (start + i) & 0x1f; + if (bus->phy_map[addr] == NULL) + mdiobus_scan(bus, addr); + + if (phydev == NULL) { + phydev = bus->phy_map[addr]; + if (phydev != NULL) + ethernet_phy_set_addr(pep, addr); + } + } + + return phydev; +} + +static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex) +{ + struct phy_device *phy = pep->phy; + ethernet_phy_reset(pep); + + phy_attach(pep->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_MII); + + if (speed == 0) { + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->supported &= PHY_BASIC_FEATURES; + phy->advertising = phy->supported | ADVERTISED_Autoneg; + } else { + phy->autoneg = AUTONEG_DISABLE; + phy->advertising = 0; + phy->speed = speed; + phy->duplex = duplex; + } + phy_start_aneg(phy); +} + +static int ethernet_phy_setup(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (pep->pd != NULL) { + if (pep->pd->init) + pep->pd->init(); + } + pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f); + if (pep->phy != NULL) + phy_init(pep, pep->pd->speed, pep->pd->duplex); + update_hash_table_mac_address(pep, NULL, dev->dev_addr); + + return 0; +} + +static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int err; + + err = phy_read_status(pep->phy); + if (err == 0) + err = phy_ethtool_gset(pep->phy, cmd); + + return err; +} + +static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + return phy_ethtool_sset(pep->phy, cmd); +} + +static void pxa168_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strncpy(info->driver, DRIVER_NAME, 32); + strncpy(info->version, DRIVER_VERSION, 32); + strncpy(info->fw_version, "N/A", 32); + strncpy(info->bus_info, "N/A", 32); +} + +static u32 pxa168_get_link(struct net_device *dev) +{ + return !!netif_carrier_ok(dev); +} + +static const struct ethtool_ops pxa168_ethtool_ops = { + .get_settings = pxa168_get_settings, + .set_settings = pxa168_set_settings, + .get_drvinfo = pxa168_get_drvinfo, + .get_link = pxa168_get_link, +}; + +static const struct net_device_ops pxa168_eth_netdev_ops = { + .ndo_open = pxa168_eth_open, + .ndo_stop = pxa168_eth_stop, + .ndo_start_xmit = pxa168_eth_start_xmit, + .ndo_set_rx_mode = pxa168_eth_set_rx_mode, + .ndo_set_mac_address = pxa168_eth_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = pxa168_eth_do_ioctl, + .ndo_change_mtu = pxa168_eth_change_mtu, + .ndo_tx_timeout = pxa168_eth_tx_timeout, +}; + +static int pxa168_eth_probe(struct platform_device *pdev) +{ + struct pxa168_eth_private *pep = NULL; + struct net_device *dev = NULL; + struct resource *res; + struct clk *clk; + int err; + + printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n"); + + clk = clk_get(&pdev->dev, "MFUCLK"); + if (IS_ERR(clk)) { + printk(KERN_ERR "%s: Fast Ethernet failed to get clock\n", + DRIVER_NAME); + return -ENODEV; + } + clk_enable(clk); + + dev = alloc_etherdev(sizeof(struct pxa168_eth_private)); + if (!dev) { + err = -ENOMEM; + goto out; + } + + platform_set_drvdata(pdev, dev); + pep = netdev_priv(dev); + pep->dev = dev; + pep->clk = clk; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -ENODEV; + goto out; + } + pep->base = ioremap(res->start, res->end - res->start + 1); + if (pep->base == NULL) { + err = -ENOMEM; + goto out; + } + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + BUG_ON(!res); + dev->irq = res->start; + dev->netdev_ops = &pxa168_eth_netdev_ops; + dev->watchdog_timeo = 2 * HZ; + dev->base_addr = 0; + SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops); + + INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); + + printk(KERN_INFO "%s:Using random mac address\n", DRIVER_NAME); + random_ether_addr(dev->dev_addr); + + pep->pd = pdev->dev.platform_data; + pep->rx_ring_size = NUM_RX_DESCS; + if (pep->pd->rx_queue_size) + pep->rx_ring_size = pep->pd->rx_queue_size; + + pep->tx_ring_size = NUM_TX_DESCS; + if (pep->pd->tx_queue_size) + pep->tx_ring_size = pep->pd->tx_queue_size; + + pep->port_num = pep->pd->port_number; + /* Hardware supports only 3 ports */ + BUG_ON(pep->port_num > 2); + netif_napi_add(dev, &pep->napi, pxa168_rx_poll, pep->rx_ring_size); + + memset(&pep->timeout, 0, sizeof(struct timer_list)); + init_timer(&pep->timeout); + pep->timeout.function = rxq_refill_timer_wrapper; + pep->timeout.data = (unsigned long)pep; + + pep->smi_bus = mdiobus_alloc(); + if (pep->smi_bus == NULL) { + err = -ENOMEM; + goto out; + } + pep->smi_bus->priv = pep; + pep->smi_bus->name = "pxa168_eth smi"; + pep->smi_bus->read = pxa168_smi_read; + pep->smi_bus->write = pxa168_smi_write; + snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); + pep->smi_bus->parent = &pdev->dev; + pep->smi_bus->phy_mask = 0xffffffff; + if (mdiobus_register(pep->smi_bus) < 0) { + err = -ENOMEM; + goto out; + } + pxa168_init_hw(pep); + err = ethernet_phy_setup(dev); + if (err) + goto out; + SET_NETDEV_DEV(dev, &pdev->dev); + err = register_netdev(dev); + if (err) + goto out; + return 0; +out: + if (pep->clk) { + clk_disable(pep->clk); + clk_put(pep->clk); + pep->clk = NULL; + } + if (pep->base) { + iounmap(pep->base); + pep->base = NULL; + } + if (dev) + free_netdev(dev); + return err; +} + +static int pxa168_eth_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (pep->htpr) { + dma_free_coherent(pep->dev->dev.parent, HASH_ADDR_TABLE_SIZE, + pep->htpr, pep->htpr_dma); + pep->htpr = NULL; + } + if (pep->clk) { + clk_disable(pep->clk); + clk_put(pep->clk); + pep->clk = NULL; + } + if (pep->phy != NULL) + phy_detach(pep->phy); + + iounmap(pep->base); + pep->base = NULL; + unregister_netdev(dev); + flush_scheduled_work(); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static void pxa168_eth_shutdown(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + eth_port_reset(dev); +} + +#ifdef CONFIG_PM +static int pxa168_eth_resume(struct platform_device *pdev) +{ + return -ENOSYS; +} + +static int pxa168_eth_suspend(struct platform_device *pdev, pm_message_t state) +{ + return -ENOSYS; +} + +#else +#define pxa168_eth_resume NULL +#define pxa168_eth_suspend NULL +#endif + +static struct platform_driver pxa168_eth_driver = { + .probe = pxa168_eth_probe, + .remove = pxa168_eth_remove, + .shutdown = pxa168_eth_shutdown, + .resume = pxa168_eth_resume, + .suspend = pxa168_eth_suspend, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init pxa168_init_module(void) +{ + return platform_driver_register(&pxa168_eth_driver); +} + +static void __exit pxa168_cleanup_module(void) +{ + platform_driver_unregister(&pxa168_eth_driver); +} + +module_init(pxa168_init_module); +module_exit(pxa168_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ethernet driver for Marvell PXA168"); +MODULE_ALIAS("platform:pxa168_eth"); diff --git a/include/linux/pxa168_eth.h b/include/linux/pxa168_eth.h new file mode 100644 index 00000000000..18d75e79560 --- /dev/null +++ b/include/linux/pxa168_eth.h @@ -0,0 +1,30 @@ +/* + *pxa168 ethernet platform device data definition file. + */ +#ifndef __LINUX_PXA168_ETH_H +#define __LINUX_PXA168_ETH_H + +struct pxa168_eth_platform_data { + int port_number; + int phy_addr; + + /* + * If speed is 0, then speed and duplex are autonegotiated. + */ + int speed; /* 0, SPEED_10, SPEED_100 */ + int duplex; /* DUPLEX_HALF or DUPLEX_FULL */ + + /* + * Override default RX/TX queue sizes if nonzero. + */ + int rx_queue_size; + int tx_queue_size; + + /* + * init callback is used for board specific initialization + * e.g on Aspenite its used to initialize the PHY transceiver. + */ + int (*init)(void); +}; + +#endif /* __LINUX_PXA168_ETH_H */ -- cgit v1.2.3-70-g09d2 From 3971a230f9573cca1cbef96dab05e2682820f1a0 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Mon, 16 Aug 2010 06:34:06 +0000 Subject: bnx2x: Fix PHY locking problem PHY locking is required between two ports for some external PHYs. Since initialization was done in the common init function (called only on the first port initialization) rather than in the port init function, there was in fact no PHY locking between the ports. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index b4ec2b02a46..f8c3f08e4ce 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -4328,10 +4328,12 @@ static int bnx2x_init_port(struct bnx2x *bp) val |= aeu_gpio_mask; REG_WR(bp, offset, val); } + bp->port.need_hw_lock = 1; break; - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: + bp->port.need_hw_lock = 1; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: /* add SPIO 5 to group 0 */ { u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : @@ -4341,7 +4343,10 @@ static int bnx2x_init_port(struct bnx2x *bp) REG_WR(bp, reg_addr, val); } break; - + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: + bp->port.need_hw_lock = 1; + break; default: break; } -- cgit v1.2.3-70-g09d2 From 96ac4f6b326450af496e82347e207b0fca7a9090 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Mon, 16 Aug 2010 06:34:07 +0000 Subject: bnx2x: Update bnx2x version to 1.52.53-4 Update bnx2x version to 1.52.53-4 Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 53af9c93e75..0c2d96ed561 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -20,8 +20,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.52.53-3" -#define DRV_MODULE_RELDATE "2010/18/04" +#define DRV_MODULE_VERSION "1.52.53-4" +#define DRV_MODULE_RELDATE "2010/16/08" #define BNX2X_BC_VER 0x040200 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -- cgit v1.2.3-70-g09d2 From 2928db4c3c62552d3caf9ab53ccc6f7ae9865a23 Mon Sep 17 00:00:00 2001 From: Andre Detsch Date: Tue, 17 Aug 2010 05:49:12 +0000 Subject: ehea: Fix synchronization between HW and SW send queue ehea: Fix synchronization between HW and SW send queue When memory is added to / removed from a partition via the Memory DLPAR mechanism, the eHEA driver has to do a couple of things to reflect the memory change in its own IO address translation tables. This involves stopping and restarting the HW queues. During this operation, it is possible that HW and SW pointer into these queues get out of sync. This results in a situation where packets that are attached to a send queue are not transmitted immediately, but delayed until further X packets have been put on the queue. This patch detects such loss of synchronization, and resets the ehea port when needed. Signed-off-by: Jan-Bernd Themann Signed-off-by: Andre Detsch Signed-off-by: David S. Miller --- drivers/net/ehea/ehea.h | 3 ++- drivers/net/ehea/ehea_main.c | 60 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0060e422f17..2ce67f6152c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0105" +#define DRV_VERSION "EHEA_0106" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -400,6 +400,7 @@ struct ehea_port_res { u32 poll_counter; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS]; + int sq_restart_flag; }; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3beba70b7de..adb5994c125 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -776,6 +776,53 @@ static int ehea_proc_rwqes(struct net_device *dev, return processed; } +#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull + +static void reset_sq_restart_flag(struct ehea_port *port) +{ + int i; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + pr->sq_restart_flag = 0; + } +} + +static void check_sqs(struct ehea_port *port) +{ + struct ehea_swqe *swqe; + int swqe_index; + int i, k; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + k = 0; + swqe = ehea_get_swqe(pr->qp, &swqe_index); + memset(swqe, 0, SWQE_HEADER_SIZE); + atomic_dec(&pr->swqe_avail); + + swqe->tx_control |= EHEA_SWQE_PURGE; + swqe->wr_id = SWQE_RESTART_CHECK; + swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION; + swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT; + swqe->immediate_data_length = 80; + + ehea_post_swqe(pr->qp, swqe); + + while (pr->sq_restart_flag == 0) { + msleep(5); + if (++k == 100) { + ehea_error("HW/SW queues out of sync"); + ehea_schedule_port_reset(pr->port); + return; + } + } + } + + return; +} + + static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) { struct sk_buff *skb; @@ -793,6 +840,13 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) cqe_counter++; rmb(); + + if (cqe->wr_id == SWQE_RESTART_CHECK) { + pr->sq_restart_flag = 1; + swqe_av++; + break; + } + if (cqe->status & EHEA_CQE_STAT_ERR_MASK) { ehea_error("Bad send completion status=0x%04X", cqe->status); @@ -2675,8 +2729,10 @@ static void ehea_flush_sq(struct ehea_port *port) int k = 0; while (atomic_read(&pr->swqe_avail) < swqe_max) { msleep(5); - if (++k == 20) + if (++k == 20) { + ehea_error("WARNING: sq not flushed completely"); break; + } } } } @@ -2917,6 +2973,7 @@ static void ehea_rereg_mrs(struct work_struct *work) port_napi_disable(port); mutex_unlock(&port->port_lock); } + reset_sq_restart_flag(port); } /* Unregister old memory region */ @@ -2951,6 +3008,7 @@ static void ehea_rereg_mrs(struct work_struct *work) mutex_lock(&port->port_lock); port_napi_enable(port); ret = ehea_restart_qps(dev); + check_sqs(port); if (!ret) netif_wake_queue(dev); mutex_unlock(&port->port_lock); -- cgit v1.2.3-70-g09d2 From 0645bab7da3cb021157e5c661ef35f1d1226785a Mon Sep 17 00:00:00 2001 From: Robert Jennings Date: Tue, 17 Aug 2010 09:15:45 +0000 Subject: ibmveth: Fix opps during MTU change on an active device This fixes the following opps which can occur when trying to deallocate receive buffer pools when changing the MTU of an active ibmveth device. Oops: Kernel access of bad area, sig: 11 [#1] NIP: d000000004db00e8 LR: d000000004db00ac CTR: 0000000000591038 REGS: c00000007fff39d0 TRAP: 0300 Not tainted (2.6.36-rc1) MSR: 8000000000009032 CR: 22248244 XER: 00000002 DAR: 0000000000000488, DSISR: 0000000042000000 TASK = c00000007c463790[6531] 'netserver' THREAD: c00000007a154000 CPU: 0 GPR00: 0000000000000000 c00000007fff3c50 d000000004dbd360 0000000000000001 GPR04: 0000000000000001 1fffffffffffffff 000000000000043c c00000007a8e9f60 GPR08: c00000007a8e9e20 0000000000000245 0000000000000488 0000000000000000 GPR12: 00000000000000c0 c000000006d70000 c00000007bfec098 c00000007bfebc2c GPR16: c00000007a157c78 0000000000000000 0000000000000001 0000000000000000 GPR20: 0000000000000001 0000000000000010 c000000000b51180 c00000007a8e9d90 GPR24: c00000007a8e9da0 c00000007a8e9580 00000000000005ea 00000000000002ff GPR28: 0000000000000004 0000000000000080 c000000000a946f8 c00000007a8e9d80 NIP [d000000004db00e8] .ibmveth_remove_buffer_from_pool+0xe8/0x130 [ibmveth] LR [d000000004db00ac] .ibmveth_remove_buffer_from_pool+0xac/0x130 [ibmveth] Call Trace: [c00000007fff3c50] [d000000004db00ac] .ibmveth_remove_buffer_from_pool+0xac/0x130 [ibmveth] (unreliable) [c00000007fff3cf0] [d000000004db31dc] .ibmveth_poll+0x30c/0x460 [ibmveth] [c00000007fff3dd0] [c00000000042c4b8] .net_rx_action+0x178/0x278 [c00000007fff3eb0] [c000000000093cf0] .__do_softirq+0x118/0x1f8 [c00000007fff3f90] [c00000000002ab3c] .call_do_softirq+0x14/0x24 [c00000007a157600] [c00000000000e3e4] .do_softirq+0xec/0x110 [c00000007a1576a0] [c000000000093394] .local_bh_enable_ip+0xb4/0xe0 [c00000007a157720] [c0000000004f0bac] ._raw_spin_unlock_bh+0x3c/0x50 [c00000007a157790] [c0000000004186e0] .release_sock+0x158/0x188 [c00000007a157840] [c000000000479660] .tcp_recvmsg+0x560/0x9b8 [c00000007a157970] [c0000000004a0d78] .inet_recvmsg+0x80/0xd8 [c00000007a157a00] [c000000000413e28] .sock_recvmsg+0x128/0x178 [c00000007a157bf0] [c0000000004164ac] .SyS_recvfrom+0xb4/0x148 [c00000007a157d70] [c000000000411f3c] .SyS_socketcall+0x274/0x360 [c00000007a157e30] [c0000000000085b4] syscall_exit+0x0/0x40 Reported-by: Rafael Camarda Silva Folco Signed-off-by: Robert Jennings Acked-by: Brian King Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2602852cc55..4734c939ad0 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1113,7 +1113,8 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) struct ibmveth_adapter *adapter = netdev_priv(dev); struct vio_dev *viodev = adapter->vdev; int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; - int i; + int i, rc; + int need_restart = 0; if (new_mtu < IBMVETH_MAX_MTU) return -EINVAL; @@ -1127,35 +1128,32 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) /* Deactivate all the buffer pools so that the next loop can activate only the buffer pools necessary to hold the new MTU */ - for (i = 0; i < IbmVethNumBufferPools; i++) - if (adapter->rx_buff_pool[i].active) { - ibmveth_free_buffer_pool(adapter, - &adapter->rx_buff_pool[i]); - adapter->rx_buff_pool[i].active = 0; - } + if (netif_running(adapter->netdev)) { + need_restart = 1; + adapter->pool_config = 1; + ibmveth_close(adapter->netdev); + adapter->pool_config = 0; + } /* Look for an active buffer pool that can hold the new MTU */ for(i = 0; irx_buff_pool[i].active = 1; if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { - if (netif_running(adapter->netdev)) { - adapter->pool_config = 1; - ibmveth_close(adapter->netdev); - adapter->pool_config = 0; - dev->mtu = new_mtu; - vio_cmo_set_dev_desired(viodev, - ibmveth_get_desired_dma - (viodev)); - return ibmveth_open(adapter->netdev); - } dev->mtu = new_mtu; vio_cmo_set_dev_desired(viodev, ibmveth_get_desired_dma (viodev)); + if (need_restart) { + return ibmveth_open(adapter->netdev); + } return 0; } } + + if (need_restart && (rc = ibmveth_open(adapter->netdev))) + return rc; + return -EINVAL; } -- cgit v1.2.3-70-g09d2 From 4be353d5169ef2477814b35fe46734a51dcecd09 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 17 Aug 2010 20:51:51 +0000 Subject: netxen: fix inconsistent lock state Spin lock rds_ring->lock is used in poll routine, so other users should use spin_lock_bh(). While posting rx buffers from netxen_nic_attach, rds_ring->lock is not required, so cleaning it instead of fixing it by spin_lock_bh(). Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_init.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index c865dda2adf..cabae7bb1fc 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1805,8 +1805,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, netxen_ctx_msg msg = 0; struct list_head *head; - spin_lock(&rds_ring->lock); - producer = rds_ring->producer; head = &rds_ring->free_list; @@ -1853,8 +1851,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, NETXEN_RCV_PRODUCER_OFFSET), msg); } } - - spin_unlock(&rds_ring->lock); } static void -- cgit v1.2.3-70-g09d2 From 772806bbbc5aa4ddf5ac0de57c1ee7c0ef94e490 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 17 Aug 2010 20:51:52 +0000 Subject: netxen: update version 4.0.74 Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ffa1b9ce1cc..6dca3574e35 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 73 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.73" +#define _NETXEN_NIC_LINUX_SUBVERSION 74 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.74" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) -- cgit v1.2.3-70-g09d2 From 9c38657cfcb739b7dc4ce9065a85b4f0c195bef8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Aug 2010 00:39:45 -0700 Subject: net: sh_eth: remove unused variable Signed-off-by: Kuninori Morimoto Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index f5a9eb1df59..79fd02bc69f 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1437,7 +1437,7 @@ static const struct net_device_ops sh_eth_netdev_ops = { static int sh_eth_drv_probe(struct platform_device *pdev) { - int ret, i, devno = 0; + int ret, devno = 0; struct resource *res; struct net_device *ndev = NULL; struct sh_eth_private *mdp; -- cgit v1.2.3-70-g09d2 From 1003201a73daed739747b9a6c2c39c57aad5878b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Aug 2010 00:42:48 +0000 Subject: qlnic: fix a race in qlcnic_get_stats() Dont clear netdev->stats, it might give transient wrong values to concurrent stat readers. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index bf6d87adda4..213e3656d95 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1983,8 +1983,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) struct qlcnic_adapter *adapter = netdev_priv(netdev); struct net_device_stats *stats = &netdev->stats; - memset(stats, 0, sizeof(*stats)); - stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes; -- cgit v1.2.3-70-g09d2 From 502820a3161e2f228125977d133dd80eea2932d1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Aug 2010 02:29:30 +0000 Subject: netxen: fix a race in netxen_nic_get_stats() Dont clear netdev->stats, it might give transient wrong values to concurrent stat readers. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index fd86e18604e..cb30df106a2 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2032,8 +2032,6 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct net_device_stats *stats = &netdev->stats; - memset(stats, 0, sizeof(*stats)); - stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes; -- cgit v1.2.3-70-g09d2 From 8539992f6091eb8206c781421312157d0c282e6e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 18 Aug 2010 00:26:34 +0000 Subject: ll_temac: Fix poll implementation Functions ll_temac_rx_irq and ll_temac_tx_irq have pointer to net_device as second parameter not pointer to temac_local. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ll_temac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 4eea3f70c5c..09b813f1c3c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -902,8 +902,8 @@ temac_poll_controller(struct net_device *ndev) disable_irq(lp->tx_irq); disable_irq(lp->rx_irq); - ll_temac_rx_irq(lp->tx_irq, lp); - ll_temac_tx_irq(lp->rx_irq, lp); + ll_temac_rx_irq(lp->tx_irq, ndev); + ll_temac_tx_irq(lp->rx_irq, ndev); enable_irq(lp->tx_irq); enable_irq(lp->rx_irq); -- cgit v1.2.3-70-g09d2 From 19833b5dffe2f2e92a1b377f9aae9d5f32239512 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Aug 2010 15:48:30 -0700 Subject: e1000e: disable ASPM L1 on 82573 On the e1000-devel mailing list, Nils Faerber reported latency issues with the 82573 LOM on a ThinkPad X60. It was found to be caused by ASPM L1; disabling it resolves the latency. The issue is present in kernels back to 2.6.34 and possibly 2.6.33. Reported-by: Nils Faerber Signed-off-by: Bruce Allan Cc: stable@kernel.org Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index a4a0d2b6eb1..f844e6c6063 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1833,6 +1833,7 @@ struct e1000_info e1000_82573_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_SWSM_ON_LOAD, + .flags2 = FLAG2_DISABLE_ASPM_L1, .pba = 20, .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, -- cgit v1.2.3-70-g09d2 From 1aef70ef125165e0114a8e475636eff242a52030 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 19 Aug 2010 15:48:52 -0700 Subject: e1000e: don't check for alternate MAC addr on parts that don't support it From: Bruce Allan The alternate MAC address feature is only supported by 80003ES2LAN and 82571 LOMs as well as a couple 82571 mezzanine cards. Checking for an alternate MAC address on other parts can fail leading to the driver not able to load. This patch limits the check for an alternate MAC address to be done only for parts that support the feature. This issue has been around since support for the feature was introduced to the e1000e driver in 2.6.34. Signed-off-by: Bruce Allan Reported-by: Fabio Varesano Cc: stable@kernel.org Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 30 +++++++++++++++++------------- drivers/net/e1000e/defines.h | 4 ++++ drivers/net/e1000e/lib.c | 10 ++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index f844e6c6063..d3d4a57e245 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -936,12 +936,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); icr = er32(ICR); - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; + if (hw->mac.type == e1000_82571) { + /* Install any alternate MAC address into RAR0 */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + return ret_val; - e1000e_set_laa_state_82571(hw, true); + e1000e_set_laa_state_82571(hw, true); + } /* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes) @@ -1618,14 +1620,16 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) { s32 ret_val = 0; - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; + if (hw->mac.type == e1000_82571) { + /* + * If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + goto out; + } ret_val = e1000_read_mac_addr_generic(hw); diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 307a72f483e..93b3bedae8d 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -621,6 +621,7 @@ #define E1000_FLASH_UPDATES 2000 /* NVM Word Offsets */ +#define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 @@ -643,6 +644,9 @@ /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define NVM_COMPAT_LOM 0x0800 + /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index df4a2792293..0fd4eb5ac5f 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -183,6 +183,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ALEN]; + ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); + if (ret_val) + goto out; + + /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ + if (!((nvm_data & NVM_COMPAT_LOM) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD))) + goto out; + ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { -- cgit v1.2.3-70-g09d2 From 1495cc9df4e81f5a8fa9b0b8f1034b14d24b7d8c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 17 Aug 2010 21:15:46 -0700 Subject: Input: sysrq - drop tty argument from sysrq ops handlers Noone is using tty argument so let's get rid of it. Acked-by: Alan Cox Acked-by: Jason Wessel Acked-by: Greg Kroah-Hartman Signed-off-by: Dmitry Torokhov --- arch/arm/kernel/etm.c | 2 +- arch/powerpc/xmon/xmon.c | 5 ++--- arch/sparc/kernel/process_64.c | 2 +- drivers/char/sysrq.c | 42 ++++++++++++++++++++--------------------- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/net/ibm_newemac/debug.c | 2 +- include/linux/sysrq.h | 6 +++++- kernel/debug/debug_core.c | 2 +- kernel/power/poweroff.c | 2 +- 9 files changed, 34 insertions(+), 31 deletions(-) (limited to 'drivers/net') diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 56418f98cd0..33c7077174d 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -230,7 +230,7 @@ static void etm_dump(void) etb_lock(t); } -static void sysrq_etm_dump(int key, struct tty_struct *tty) +static void sysrq_etm_dump(int key) { dev_dbg(tracer.dev, "Dumping ETB buffer\n"); etm_dump(); diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 0554445200b..d17d04cfb2c 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2880,15 +2880,14 @@ static void xmon_init(int enable) } #ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_handle_xmon(int key, struct tty_struct *tty) +static void sysrq_handle_xmon(int key) { /* ensure xmon is enabled */ xmon_init(1); debugger(get_irq_regs()); } -static struct sysrq_key_op sysrq_xmon_op = -{ +static struct sysrq_key_op sysrq_xmon_op = { .handler = sysrq_handle_xmon, .help_msg = "Xmon", .action_msg = "Entering xmon", diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index dbe81a368b4..25b01b43b40 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -303,7 +303,7 @@ void arch_trigger_all_cpu_backtrace(void) #ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_handle_globreg(int key, struct tty_struct *tty) +static void sysrq_handle_globreg(int key) { arch_trigger_all_cpu_backtrace(); } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 878ac0c2cc6..a892a3c249d 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -76,7 +76,7 @@ static int __init sysrq_always_enabled_setup(char *str) __setup("sysrq_always_enabled", sysrq_always_enabled_setup); -static void sysrq_handle_loglevel(int key, struct tty_struct *tty) +static void sysrq_handle_loglevel(int key) { int i; @@ -93,7 +93,7 @@ static struct sysrq_key_op sysrq_loglevel_op = { }; #ifdef CONFIG_VT -static void sysrq_handle_SAK(int key, struct tty_struct *tty) +static void sysrq_handle_SAK(int key) { struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; schedule_work(SAK_work); @@ -109,7 +109,7 @@ static struct sysrq_key_op sysrq_SAK_op = { #endif #ifdef CONFIG_VT -static void sysrq_handle_unraw(int key, struct tty_struct *tty) +static void sysrq_handle_unraw(int key) { struct kbd_struct *kbd = &kbd_table[fg_console]; @@ -126,7 +126,7 @@ static struct sysrq_key_op sysrq_unraw_op = { #define sysrq_unraw_op (*(struct sysrq_key_op *)NULL) #endif /* CONFIG_VT */ -static void sysrq_handle_crash(int key, struct tty_struct *tty) +static void sysrq_handle_crash(int key) { char *killer = NULL; @@ -141,7 +141,7 @@ static struct sysrq_key_op sysrq_crash_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_reboot(int key, struct tty_struct *tty) +static void sysrq_handle_reboot(int key) { lockdep_off(); local_irq_enable(); @@ -154,7 +154,7 @@ static struct sysrq_key_op sysrq_reboot_op = { .enable_mask = SYSRQ_ENABLE_BOOT, }; -static void sysrq_handle_sync(int key, struct tty_struct *tty) +static void sysrq_handle_sync(int key) { emergency_sync(); } @@ -165,7 +165,7 @@ static struct sysrq_key_op sysrq_sync_op = { .enable_mask = SYSRQ_ENABLE_SYNC, }; -static void sysrq_handle_show_timers(int key, struct tty_struct *tty) +static void sysrq_handle_show_timers(int key) { sysrq_timer_list_show(); } @@ -176,7 +176,7 @@ static struct sysrq_key_op sysrq_show_timers_op = { .action_msg = "Show clockevent devices & pending hrtimers (no others)", }; -static void sysrq_handle_mountro(int key, struct tty_struct *tty) +static void sysrq_handle_mountro(int key) { emergency_remount(); } @@ -188,7 +188,7 @@ static struct sysrq_key_op sysrq_mountro_op = { }; #ifdef CONFIG_LOCKDEP -static void sysrq_handle_showlocks(int key, struct tty_struct *tty) +static void sysrq_handle_showlocks(int key) { debug_show_all_locks(); } @@ -226,7 +226,7 @@ static void sysrq_showregs_othercpus(struct work_struct *dummy) static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus); -static void sysrq_handle_showallcpus(int key, struct tty_struct *tty) +static void sysrq_handle_showallcpus(int key) { /* * Fall back to the workqueue based printing if the @@ -252,7 +252,7 @@ static struct sysrq_key_op sysrq_showallcpus_op = { }; #endif -static void sysrq_handle_showregs(int key, struct tty_struct *tty) +static void sysrq_handle_showregs(int key) { struct pt_regs *regs = get_irq_regs(); if (regs) @@ -266,7 +266,7 @@ static struct sysrq_key_op sysrq_showregs_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_showstate(int key, struct tty_struct *tty) +static void sysrq_handle_showstate(int key) { show_state(); } @@ -277,7 +277,7 @@ static struct sysrq_key_op sysrq_showstate_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) +static void sysrq_handle_showstate_blocked(int key) { show_state_filter(TASK_UNINTERRUPTIBLE); } @@ -291,7 +291,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { #ifdef CONFIG_TRACING #include -static void sysrq_ftrace_dump(int key, struct tty_struct *tty) +static void sysrq_ftrace_dump(int key) { ftrace_dump(DUMP_ALL); } @@ -305,7 +305,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = { #define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL) #endif -static void sysrq_handle_showmem(int key, struct tty_struct *tty) +static void sysrq_handle_showmem(int key) { show_mem(); } @@ -330,7 +330,7 @@ static void send_sig_all(int sig) } } -static void sysrq_handle_term(int key, struct tty_struct *tty) +static void sysrq_handle_term(int key) { send_sig_all(SIGTERM); console_loglevel = 8; @@ -349,7 +349,7 @@ static void moom_callback(struct work_struct *ignored) static DECLARE_WORK(moom_work, moom_callback); -static void sysrq_handle_moom(int key, struct tty_struct *tty) +static void sysrq_handle_moom(int key) { schedule_work(&moom_work); } @@ -361,7 +361,7 @@ static struct sysrq_key_op sysrq_moom_op = { }; #ifdef CONFIG_BLOCK -static void sysrq_handle_thaw(int key, struct tty_struct *tty) +static void sysrq_handle_thaw(int key) { emergency_thaw_all(); } @@ -373,7 +373,7 @@ static struct sysrq_key_op sysrq_thaw_op = { }; #endif -static void sysrq_handle_kill(int key, struct tty_struct *tty) +static void sysrq_handle_kill(int key) { send_sig_all(SIGKILL); console_loglevel = 8; @@ -385,7 +385,7 @@ static struct sysrq_key_op sysrq_kill_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -static void sysrq_handle_unrt(int key, struct tty_struct *tty) +static void sysrq_handle_unrt(int key) { normalize_rt_tasks(); } @@ -520,7 +520,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; - op_p->handler(key, tty); + op_p->handler(key); } else { printk("This sysrq operation is disabled.\n"); } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index de82e201d68..5efd6d6742e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -369,7 +369,7 @@ static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) } static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn); -static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3) +static void drm_fb_helper_sysrq(int dummy1) { schedule_work(&drm_fb_helper_restore_work); } diff --git a/drivers/net/ibm_newemac/debug.c b/drivers/net/ibm_newemac/debug.c index 3995fafc1e0..8c6c1e2a875 100644 --- a/drivers/net/ibm_newemac/debug.c +++ b/drivers/net/ibm_newemac/debug.c @@ -238,7 +238,7 @@ void emac_dbg_dump_all(void) } #if defined(CONFIG_MAGIC_SYSRQ) -static void emac_sysrq_handler(int key, struct tty_struct *tty) +static void emac_sysrq_handler(int key) { emac_dbg_dump_all(); } diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 609e8ca5f53..4ee65031511 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -31,7 +31,7 @@ struct tty_struct; #define SYSRQ_ENABLE_RTNICE 0x0100 struct sysrq_key_op { - void (*handler)(int, struct tty_struct *); + void (*handler)(int); char *help_msg; char *action_msg; int enable_mask; @@ -58,6 +58,10 @@ static inline void handle_sysrq(int key, struct tty_struct *tty) { } +static inline void __handle_sysrq(int key, struct tty_struct *tty, int check_mask); +{ +} + static inline int register_sysrq_key(int key, struct sysrq_key_op *op) { return -EINVAL; diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 3c2d4972d23..de407c78178 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -741,7 +741,7 @@ static struct console kgdbcons = { }; #ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_handle_dbg(int key, struct tty_struct *tty) +static void sysrq_handle_dbg(int key) { if (!dbg_io_ops) { printk(KERN_CRIT "ERROR: No KGDB I/O module available\n"); diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c index e8b33700627..d52359374e8 100644 --- a/kernel/power/poweroff.c +++ b/kernel/power/poweroff.c @@ -24,7 +24,7 @@ static void do_poweroff(struct work_struct *dummy) static DECLARE_WORK(poweroff_work, do_poweroff); -static void handle_poweroff(int key, struct tty_struct *tty) +static void handle_poweroff(int key) { /* run sysrq poweroff on boot cpu */ schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work); -- cgit v1.2.3-70-g09d2 From f95d76ab82c381ce2221fbe75f331ff1478732db Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 23 Aug 2010 12:39:29 +0200 Subject: ipheth: add support for iPhone 4 This adds support for the iPhone 4 to the ipheth driver. Acked-by: Diego Giagio Signed-off-by: Jens Axboe --- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 08e7b6abacd..8ed30fa35d0 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -58,6 +58,7 @@ #define USB_PRODUCT_IPHONE 0x1290 #define USB_PRODUCT_IPHONE_3G 0x1292 #define USB_PRODUCT_IPHONE_3GS 0x1294 +#define USB_PRODUCT_IPHONE_4 0x1297 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -92,6 +93,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); -- cgit v1.2.3-70-g09d2 From 7b589a35a1063b52f98c8b0f1b8f69afe91c3dba Mon Sep 17 00:00:00 2001 From: Yinglin Luan Date: Sun, 22 Aug 2010 21:56:19 +0000 Subject: netxen: fix poll implementation Function netxen_intr has pointer to nx_host_sds_ring as second parameter not pointer to netxen_adapter. Signed-off-by: Yinglin Luan Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cb30df106a2..73d31459223 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2131,9 +2131,16 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_NET_POLL_CONTROLLER static void netxen_nic_poll_controller(struct net_device *netdev) { + int ring; + struct nx_host_sds_ring *sds_ring; struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + disable_irq(adapter->irq); - netxen_intr(adapter->irq, adapter); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netxen_intr(adapter->irq, sds_ring); + } enable_irq(adapter->irq); } #endif -- cgit v1.2.3-70-g09d2 From bf82791ed667758a0f18a4b76be2d931d2c1b39d Mon Sep 17 00:00:00 2001 From: Yinglin Luan Date: Sun, 22 Aug 2010 21:57:56 +0000 Subject: qlcnic: fix poll implementation Function qlcnic_intr has pointer to qlcnic_host_sds_ring as second parameter not pointer to qlcnic_adapter. Signed-off-by: Yinglin Luan Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 213e3656d95..66eea597202 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2188,9 +2188,16 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev) { + int ring; + struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + disable_irq(adapter->irq); - qlcnic_intr(adapter->irq, adapter); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + qlcnic_intr(adapter->irq, sds_ring); + } enable_irq(adapter->irq); } #endif -- cgit v1.2.3-70-g09d2 From aa25ab7d943a5e1e6bcc2a65ff6669144f5b5d60 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 11 Aug 2010 05:12:57 +0000 Subject: 3c59x: Fix deadlock between boomerang_interrupt and boomerang_start_tx If netconsole is in use, there is a possibility for deadlock in 3c59x between boomerang_interrupt and boomerang_start_xmit. Both routines take the vp->lock, and if netconsole is in use, a pr_* call from the boomerang_interrupt routine will result in the netconsole code attempting to trnasmit an skb, which can try to take the same spin lock, resulting in deadlock. The fix is pretty straightforward. This patch allocats a bit in the 3c59x private structure to indicate that its handling an interrupt. If we get into the transmit routine and that bit is set, we can be sure that we have recursed and will deadlock if we continue, so instead we just return NETDEV_TX_BUSY, so the stack requeues the skb to try again later. Signed-off-by: Neil Horman Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c754d88e5ec..c685a55fc2f 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -633,7 +633,8 @@ struct vortex_private { open:1, medialock:1, must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ - large_frames:1; /* accept large frames */ + large_frames:1, /* accept large frames */ + handling_irq:1; /* private in_irq indicator */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -2133,6 +2134,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->name, vp->cur_tx); } + /* + * We can't allow a recursion from our interrupt handler back into the + * tx routine, as they take the same spin lock, and that causes + * deadlock. Just return NETDEV_TX_BUSY and let the stack try again in + * a bit + */ + if (vp->handling_irq) + return NETDEV_TX_BUSY; + if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { if (vortex_debug > 0) pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", @@ -2335,11 +2345,13 @@ boomerang_interrupt(int irq, void *dev_id) ioaddr = vp->ioaddr; + /* * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout * and boomerang_start_xmit */ spin_lock(&vp->lock); + vp->handling_irq = 1; status = ioread16(ioaddr + EL3_STATUS); @@ -2447,6 +2459,7 @@ boomerang_interrupt(int irq, void *dev_id) pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: + vp->handling_irq = 0; spin_unlock(&vp->lock); return IRQ_HANDLED; } -- cgit v1.2.3-70-g09d2 From 9dc002d8d9c2af837e789b5bb88c61a8b32c1be8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Aug 2010 12:21:13 -0700 Subject: caif-driver: add HAS_DMA dependency Fix this error on an s390 allyesconfig build: linux-2.6/drivers/net/caif/caif_spi.c:98: undefined reference to `dma_free_coherent' Cc: Sjur Braendeland Signed-off-by: Heiko Carstens Signed-off-by: David S. Miller --- drivers/net/caif/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig index 631a6242b01..75bfc3a9d95 100644 --- a/drivers/net/caif/Kconfig +++ b/drivers/net/caif/Kconfig @@ -15,7 +15,7 @@ config CAIF_TTY config CAIF_SPI_SLAVE tristate "CAIF SPI transport driver for slave interface" - depends on CAIF + depends on CAIF && HAS_DMA default n ---help--- The CAIF Link layer SPI Protocol driver for Slave SPI interface. -- cgit v1.2.3-70-g09d2 From ef24b16b5d67c815874ed2d0e2581db629661ba3 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Tue, 24 Aug 2010 14:46:12 -0700 Subject: phylib: Fix race between returning phydev and calling adjust_link It is possible that phylib will call adjust_link before returning from {,of_}phy_connect(), which may cause the following [very rare, though] oops upon reopening the device: Unable to handle kernel paging request for data at address 0x0000024c Oops: Kernel access of bad area, sig: 11 [#1] PREEMPT SMP NR_CPUS=2 LTT NESTING LEVEL : 0 P1021 RDB Modules linked in: NIP: c0345dac LR: c0345dac CTR: c0345d84 TASK = dffab6b0[30] 'events/0' THREAD: c0d24000 CPU: 0 [...] NIP [c0345dac] adjust_link+0x28/0x19c LR [c0345dac] adjust_link+0x28/0x19c Call Trace: [c0d25f00] [000045e1] 0x45e1 (unreliable) [c0d25f30] [c036c158] phy_state_machine+0x3ac/0x554 [...] Here is why. Drivers store phydev in their private structures, e.g. gianfar driver: static int init_phy(struct net_device *dev) { ... priv->phydev = of_phy_connect(...); ... } So that adjust_link could retrieve it back: static void adjust_link(struct net_device *dev) { ... struct phy_device *phydev = priv->phydev; ... } If the device has been opened before, then phydev->state is set to PHY_HALTED (or undefined if the driver didn't call phy_stop()). Now, phy_connect starts the PHY state machine before returning phydev to the driver: phy_start_machine(phydev, NULL); if (phydev->irq > 0) phy_start_interrupts(phydev); return phydev; The time between 'phy_start_machine()' and 'return phydev' is undefined. The start machine routine delays execution for 1 second, which is enough for most cases. But under heavy load, or if you're unlucky, it is quite possible that PHY state machine will execute before phy_connect() returns, and so adjust_link callback will try to dereference phydev, which is not yet ready. To fix the issue, simply initialize the PHY's state to PHY_READY during phy_attach(). This will ensure that phylib won't call adjust_link before phy_start(). Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index c0761197c07..16ddc77313c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -466,6 +466,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->interface = interface; + phydev->state = PHY_READY; + /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) */ -- cgit v1.2.3-70-g09d2 From 4169591fd7c260b2b0b4e8f4d51f63f5b15ad78a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Aug 2010 06:52:46 +0000 Subject: pxa168_eth: remove unneeded null check "pep->pd" isn't checked consistently in this function. For example it's dereferenced unconditionally on the next line after the end of the if condition. This function is only called from pxa168_eth_probe() and pep->pd is always non-NULL so I removed the check. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index ecc64d750cc..857a68115a5 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1414,10 +1414,8 @@ static int ethernet_phy_setup(struct net_device *dev) { struct pxa168_eth_private *pep = netdev_priv(dev); - if (pep->pd != NULL) { - if (pep->pd->init) - pep->pd->init(); - } + if (pep->pd->init) + pep->pd->init(); pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f); if (pep->phy != NULL) phy_init(pep, pep->pd->speed, pep->pd->duplex); -- cgit v1.2.3-70-g09d2 From 945c7c73e2e81d68e3e2970afd95254e8f153fc9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Aug 2010 06:53:33 +0000 Subject: pxa168_eth: fix error handling in prope A couple issues here: * Some resources weren't released. * If alloc_etherdev() failed it would have caused a NULL dereference because "pep" would be null when we checked "if (pep->clk)". * Also it's better to propagate the error codes from mdiobus_register() instead of just returning -ENOMEM. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 857a68115a5..302fb480374 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1497,7 +1497,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof(struct pxa168_eth_private)); if (!dev) { err = -ENOMEM; - goto out; + goto err_clk; } platform_set_drvdata(pdev, dev); @@ -1507,12 +1507,12 @@ static int pxa168_eth_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { err = -ENODEV; - goto out; + goto err_netdev; } pep->base = ioremap(res->start, res->end - res->start + 1); if (pep->base == NULL) { err = -ENOMEM; - goto out; + goto err_netdev; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); BUG_ON(!res); @@ -1549,7 +1549,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep->smi_bus = mdiobus_alloc(); if (pep->smi_bus == NULL) { err = -ENOMEM; - goto out; + goto err_base; } pep->smi_bus->priv = pep; pep->smi_bus->name = "pxa168_eth smi"; @@ -1558,31 +1558,31 @@ static int pxa168_eth_probe(struct platform_device *pdev) snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); pep->smi_bus->parent = &pdev->dev; pep->smi_bus->phy_mask = 0xffffffff; - if (mdiobus_register(pep->smi_bus) < 0) { - err = -ENOMEM; - goto out; - } + err = mdiobus_register(pep->smi_bus); + if (err) + goto err_free_mdio; + pxa168_init_hw(pep); err = ethernet_phy_setup(dev); if (err) - goto out; + goto err_mdiobus; SET_NETDEV_DEV(dev, &pdev->dev); err = register_netdev(dev); if (err) - goto out; + goto err_mdiobus; return 0; -out: - if (pep->clk) { - clk_disable(pep->clk); - clk_put(pep->clk); - pep->clk = NULL; - } - if (pep->base) { - iounmap(pep->base); - pep->base = NULL; - } - if (dev) - free_netdev(dev); + +err_mdiobus: + mdiobus_unregister(pep->smi_bus); +err_free_mdio: + mdiobus_free(pep->smi_bus); +err_base: + iounmap(pep->base); +err_netdev: + free_netdev(dev); +err_clk: + clk_disable(clk); + clk_put(clk); return err; } -- cgit v1.2.3-70-g09d2 From 4f2c85106883bada5167e1d42a0409e063da8895 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Aug 2010 06:54:20 +0000 Subject: pxa168_eth: update call to phy_mii_ioctl() The phy_mii_ioctl() function changed recently. It now takes a struct ifreq pointer directly. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 302fb480374..f324b767f68 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1350,7 +1350,7 @@ static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, { struct pxa168_eth_private *pep = netdev_priv(dev); if (pep->phy != NULL) - return phy_mii_ioctl(pep->phy, if_mii(ifr), cmd); + return phy_mii_ioctl(pep->phy, ifr, cmd); return -EOPNOTSUPP; } -- cgit v1.2.3-70-g09d2 From b2bc85631e72485b984bcd202a104591874babba Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Aug 2010 06:55:05 +0000 Subject: pxa168_eth: silence gcc warnings Casting "pep->tx_desc_dma" to to a struct tx_desc pointer makes gcc complain: drivers/net/pxa168_eth.c:657: warning: cast to pointer from integer of different size Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index f324b767f68..410ea0a6137 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -654,15 +654,15 @@ static void eth_port_start(struct net_device *dev) /* Assignment of Tx CTRP of given queue */ tx_curr_desc = pep->tx_curr_desc_q; wrl(pep, ETH_C_TX_DESC_1, - (u32) ((struct tx_desc *)pep->tx_desc_dma + tx_curr_desc)); + (u32) (pep->tx_desc_dma + tx_curr_desc * sizeof(struct tx_desc))); /* Assignment of Rx CRDP of given queue */ rx_curr_desc = pep->rx_curr_desc_q; wrl(pep, ETH_C_RX_DESC_0, - (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); + (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc))); wrl(pep, ETH_F_RX_DESC_0, - (u32) ((struct rx_desc *)pep->rx_desc_dma + rx_curr_desc)); + (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc))); /* Clear all interrupts */ wrl(pep, INT_CAUSE, 0); -- cgit v1.2.3-70-g09d2 From fe5f098055ed7f701bfb16f8f87378cf67de9a0e Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 26 Aug 2010 08:27:58 +0000 Subject: qlge: reset the chip before freeing the buffers Qlge is freeing the buffers before stopping the card DMA, and this can cause some severe error, as a EEH event on PPC. This patch just stop the card and then free the resources. Signed-off-by: Breno Leitao Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8d63f69b27d..5f89e83501f 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3919,12 +3919,12 @@ static int ql_adapter_down(struct ql_adapter *qdev) for (i = 0; i < qdev->rss_ring_count; i++) netif_napi_del(&qdev->rx_ring[i].napi); - ql_free_rx_buffers(qdev); - status = ql_adapter_reset(qdev); if (status) netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n", qdev->func); + ql_free_rx_buffers(qdev); + return status; } -- cgit v1.2.3-70-g09d2 From 557de5eb29caeab56c2f97b49eec02e32a2cbe32 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 22 Aug 2010 14:22:40 +0300 Subject: libertas: if_sdio: fix buffer alignment in struct if_sdio_card The commit 886275ce41a9751117367fb387ed171049eb6148 (param: lock if_sdio's lbs_helper_name and lbs_fw_name against sysfs changes) introduced new fields into the if_sdio_card structure. It caused missalignment of the if_sdio_card.buffer field and failure at driver load time: ~# modprobe libertas_sdio [ 62.315124] libertas_sdio: Libertas SDIO driver [ 62.319976] libertas_sdio: Copyright Pierre Ossman [ 63.020629] DMA misaligned error with device 48 [ 63.025207] mmci-omap-hs mmci-omap-hs.1: unexpected dma status 800 [ 66.005035] libertas: command 0x0003 timed out [ 66.009826] libertas: Timeout submitting command 0x0003 [ 66.016296] libertas: PREP_CMD: command 0x0003 failed: -110 Adding explicit alignment attribute for the if_sdio_card.buffer field fixes this problem. Signed-off-by: Mike Rapoport Acked-by: Marek Vasut Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346a755..382f2371a1a 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -126,7 +126,7 @@ struct if_sdio_card { const char *helper; const char *firmware; - u8 buffer[65536]; + u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; struct if_sdio_packet *packets; -- cgit v1.2.3-70-g09d2 From 7619b1b2e2b96842459f499fd48ec32e3d223d02 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Sat, 28 Aug 2010 12:45:01 +0000 Subject: pcnet_cs: add new_id pcnet_cs: add new_id: "KENTRONICS KEP-230" 10Base-T PCMCIA card. Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bfdef72c5d5..7fd8c55288c 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1644,6 +1644,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), + PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616), PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), -- cgit v1.2.3-70-g09d2 From d8e1ba76d619dbc0be8fbeee4e6c683b5c812d3a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 24 Aug 2010 15:27:34 -0400 Subject: ath5k: check return value of ieee80211_get_tx_rate This avoids a NULL pointer dereference as reported here: https://bugzilla.redhat.com/show_bug.cgi?id=625889 When the WARN condition is hit in ieee80211_get_tx_rate, it will return NULL. So, we need to check the return value and avoid dereferencing it in that case. Signed-off-by: John W. Linville Cc: stable@kernel.org Acked-by: Bob Copeland --- drivers/net/wireless/ath/ath5k/base.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfec689..d77ce9906b6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1327,6 +1327,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, PCI_DMA_TODEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); + if (!rate) { + ret = -EINVAL; + goto err_unmap; + } if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; -- cgit v1.2.3-70-g09d2 From f880c2050f30b23c9b6f80028c09f76e693bf309 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 24 Aug 2010 22:54:05 +0200 Subject: p54: fix tx feedback status flag check Michael reported that p54* never really entered power save mode, even tough it was enabled. It turned out that upon a power save mode change the firmware will set a special flag onto the last outgoing frame tx status (which in this case is almost always the designated PSM nullfunc frame). This flag confused the driver; It erroneously reported transmission failures to the stack, which then generated the next nullfunc. and so on... Cc: Reported-by: Michael Buesch Tested-by: Michael Buesch Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 173aec3d6e7..0e937dc0c9c 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -446,7 +446,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (!payload->status)) + !(payload->status & P54_TX_FAILED)) info->flags |= IEEE80211_TX_STAT_ACK; if (payload->status & P54_TX_PSM_CANCELLED) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; -- cgit v1.2.3-70-g09d2 From 803288e61e346ba367373bc7d5eeb6e11c81a33c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:32 -0400 Subject: ath9k_hw: Fix EEPROM uncompress block reading on AR9003 The EEPROM is compressed on AR9003, upon decompression the wrong upper limit was being used for the block which prevented the 5 GHz CTL indexes from being used, which are stored towards the end of the EEPROM block. This fix allows the actual intended regulatory limits to be used on AR9003 hardware. Cc: stable@kernel.org [2.6.36+] Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index b883b174385..057fb69ddf7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -797,7 +797,7 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, length = block[it+1]; length &= 0xff; - if (length > 0 && spot >= 0 && spot+length < mdataSize) { + if (length > 0 && spot >= 0 && spot+length <= mdataSize) { ath_print(common, ATH_DBG_EEPROM, "Restore at %d: spot=%d " "offset=%d length=%d\n", -- cgit v1.2.3-70-g09d2 From 904879748d7439a6dabdc6be9aad983e216b027d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Aug 2010 19:26:33 -0400 Subject: ath9k_hw: fix parsing of HT40 5 GHz CTLs The 5 GHz CTL indexes were not being read for all hardware devices due to the masking out through the CTL_MODE_M mask being one bit too short. Without this the calibrated regulatory maximum values were not being picked up when devices operate on 5 GHz in HT40 mode. The final output power used for Atheros devices is the minimum between the calibrated CTL values and what CRDA provides. Cc: stable@kernel.org [2.6.27+] Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/regd.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7f48df1e290..0b09db0f8e7 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -62,7 +62,7 @@ #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 +#define CTL_MODE_M 0xf #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index a1c39526161..345dd9721b4 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -31,7 +31,6 @@ enum ctl_group { #define NO_CTL 0xff #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 -- cgit v1.2.3-70-g09d2 From 9f1a1fca35066117353994bff80a5115cddad7a2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 1 Sep 2010 08:55:23 -0600 Subject: of: Fix missing includes - ll_temac It is the next patch which is fixing missing header which were removed from prom.h. Related patches: "of/address: Clean up function declarations" (sha1 id 22ae782f8) "of: Fix missing includes" (sha1 id f1ca09b2b) Signed-off-by: Michal Simek Signed-off-by: Grant Likely --- drivers/net/ll_temac_main.c | 1 + drivers/net/ll_temac_mdio.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index bdf2149e529..87f0a93b165 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include /* needed for sizeof(tcphdr) */ diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c index 5ae28c975b3..8cf9d4f56bb 100644 --- a/drivers/net/ll_temac_mdio.c +++ b/drivers/net/ll_temac_mdio.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-70-g09d2 From 9c01ae58d4fee39e2af5b1379ee5431dd585cf62 Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Sun, 29 Aug 2010 21:21:38 +0000 Subject: pxa168_eth: fix a mdiobus leak mdiobus resources must be released on exit Signed-off-by: Denis Kirjanov Acked-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 410ea0a6137..85eddda276b 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -1606,6 +1606,8 @@ static int pxa168_eth_remove(struct platform_device *pdev) iounmap(pep->base); pep->base = NULL; + mdiobus_unregister(pep->smi_bus); + mdiobus_free(pep->smi_bus); unregister_netdev(dev); flush_scheduled_work(); free_netdev(dev); -- cgit v1.2.3-70-g09d2 From de6be6c1f77798c4da38301693d33aff1cd76e84 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 30 Aug 2010 07:51:17 +0000 Subject: sky2: don't do GRO on second port There's something very important I forgot to tell you. What? Don't cross the GRO streams. Why? It would be bad. I'm fuzzy on the whole good/bad thing. What do you mean, "bad"? Try to imagine all the Internet as you know it stopping instantaneously and every bit in every packet swapping at the speed of light. Total packet reordering. Right. That's bad. Okay. All right. Important safety tip. Thanks, Hubert The simplest way to stop this is just avoid doing GRO on the second port. Very few Marvell boards support two ports per ring, and GRO is just an optimization. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 194e5cf8c76..a6ff113d34b 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2520,24 +2520,27 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } -static inline void sky2_skb_rx(const struct sky2_port *sky2, +static inline void sky2_skb_rx(struct napi_struct *napi, + const struct sky2_port *sky2, u32 status, struct sk_buff *skb) { #ifdef SKY2_VLAN_TAG_USED - u16 vlan_tag = be16_to_cpu(sky2->rx_tag); if (sky2->vlgrp && (status & GMR_FS_VLAN)) { - if (skb->ip_summed == CHECKSUM_NONE) + u16 vlan_tag = be16_to_cpu(sky2->rx_tag); + + if (skb->ip_summed == CHECKSUM_NONE || + sky2->netdev != napi->dev) vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag); else - vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp, - vlan_tag, skb); + vlan_gro_receive(napi, sky2->vlgrp, vlan_tag, skb); return; } #endif - if (skb->ip_summed == CHECKSUM_NONE) + if (skb->ip_summed == CHECKSUM_NONE || + sky2->netdev != napi->dev) netif_receive_skb(skb); else - napi_gro_receive(&sky2->hw->napi, skb); + napi_gro_receive(napi, skb); } static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, @@ -2638,7 +2641,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) skb->protocol = eth_type_trans(skb, dev); - sky2_skb_rx(sky2, status, skb); + sky2_skb_rx(&hw->napi, sky2, status, skb); /* Stop after net poll weight */ if (++work_done >= to_do) -- cgit v1.2.3-70-g09d2 From 24cd804d1dc60a74c53da983094df3516500c276 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 30 Aug 2010 14:15:33 +0000 Subject: 3c59x: Remove incorrect locking; correct documented lock hierarchy vortex_ioctl() was grabbing vortex_private::lock around its call to generic_mii_ioctl(). This is no longer necessary since there are more specific locks which the mdio_{read,write}() functions will obtain. Worse, those functions do not save and restore IRQ flags when locking the MII state, so interrupts will be enabled when generic_mii_ioctl() returns. Since there is currently no need for any function to call mdio_{read,write}() while holding another spinlock, do not change them to save and restore IRQ flags but remove the specification of ordering between vortex_private::lock and vortex_private::mii_lock. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c685a55fc2f..a045559c81c 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -647,7 +647,7 @@ struct vortex_private { u16 io_size; /* Size of PCI region (for release_region) */ /* Serialises access to hardware other than MII and variables below. - * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ + * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */ spinlock_t lock; spinlock_t mii_lock; /* Serialises access to MII */ @@ -2984,7 +2984,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int err; struct vortex_private *vp = netdev_priv(dev); - unsigned long flags; pci_power_t state = 0; if(VORTEX_PCI(vp)) @@ -2994,9 +2993,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if(state != 0) pci_set_power_state(VORTEX_PCI(vp), PCI_D0); - spin_lock_irqsave(&vp->lock, flags); err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irqrestore(&vp->lock, flags); if(state != 0) pci_set_power_state(VORTEX_PCI(vp), state); -- cgit v1.2.3-70-g09d2 From 5e4e7573e1ec286120109e73bf54cff465488725 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 2 Sep 2010 09:39:09 -0700 Subject: Revert "sky2: don't do GRO on second port" This reverts commit de6be6c1f77798c4da38301693d33aff1cd76e84. After some discussion with Jarek Poplawski and Eric Dumazet, we've decided that this change is incorrect. Signed-off-by: David S. Miller --- drivers/net/sky2.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a6ff113d34b..194e5cf8c76 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2520,27 +2520,24 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } -static inline void sky2_skb_rx(struct napi_struct *napi, - const struct sky2_port *sky2, +static inline void sky2_skb_rx(const struct sky2_port *sky2, u32 status, struct sk_buff *skb) { #ifdef SKY2_VLAN_TAG_USED + u16 vlan_tag = be16_to_cpu(sky2->rx_tag); if (sky2->vlgrp && (status & GMR_FS_VLAN)) { - u16 vlan_tag = be16_to_cpu(sky2->rx_tag); - - if (skb->ip_summed == CHECKSUM_NONE || - sky2->netdev != napi->dev) + if (skb->ip_summed == CHECKSUM_NONE) vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag); else - vlan_gro_receive(napi, sky2->vlgrp, vlan_tag, skb); + vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp, + vlan_tag, skb); return; } #endif - if (skb->ip_summed == CHECKSUM_NONE || - sky2->netdev != napi->dev) + if (skb->ip_summed == CHECKSUM_NONE) netif_receive_skb(skb); else - napi_gro_receive(napi, skb); + napi_gro_receive(&sky2->hw->napi, skb); } static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, @@ -2641,7 +2638,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) skb->protocol = eth_type_trans(skb, dev); - sky2_skb_rx(&hw->napi, sky2, status, skb); + sky2_skb_rx(sky2, status, skb); /* Stop after net poll weight */ if (++work_done >= to_do) -- cgit v1.2.3-70-g09d2 From 1ef78abec6b5e9e3062e3ae6660eabaf055a718d Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 3 Sep 2010 06:17:10 +0000 Subject: be2net: fix net-snmp error because of wrong packet stats Wrong packet statistics for multicast Rx was causing net-snmp error messages every 15 seconds. Instead of picking the multicast stats from hardware, now maintain it in the driver itself. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_ethtool.c | 1 + drivers/net/benet/be_hw.h | 7 +++++-- drivers/net/benet/be_main.c | 15 +++++++++++---- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 99197bd54da..53306bf3f40 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -181,6 +181,7 @@ struct be_drvr_stats { u64 be_rx_bytes_prev; u64 be_rx_pkts; u32 be_rx_rate; + u32 be_rx_mcast_pkt; /* number of non ether type II frames dropped where * frame len > length field of Mac Hdr */ u32 be_802_3_dropped_frames; diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cd16243c7c3..13f0abbc520 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(be_rx_events)}, {DRVSTAT_INFO(be_tx_compl)}, {DRVSTAT_INFO(be_rx_compl)}, + {DRVSTAT_INFO(be_rx_mcast_pkt)}, {DRVSTAT_INFO(be_ethrx_post_fail)}, {DRVSTAT_INFO(be_802_3_dropped_frames)}, {DRVSTAT_INFO(be_802_3_malformed_frames)}, diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 5d38046402b..a2ec5df0d73 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -167,8 +167,11 @@ #define FLASH_FCoE_BIOS_START_g3 (13631488) #define FLASH_REDBOOT_START_g3 (262144) - - +/************* Rx Packet Type Encoding **************/ +#define BE_UNICAST_PACKET 0 +#define BE_MULTICAST_PACKET 1 +#define BE_BROADCAST_PACKET 2 +#define BE_RSVD_PACKET 3 /* * BE descriptors: host memory data structures whose formats diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 74e146f470c..a5a24e6c773 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter) dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; + dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt; /* bad pkts received */ dev_stats->rx_errors = port_stats->rx_crc_errors + @@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter) /* no space available in linux */ dev_stats->tx_dropped = 0; - dev_stats->multicast = port_stats->rx_multicast_frames; dev_stats->collisions = 0; /* detailed tx_errors */ @@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter) } static void be_rx_stats_update(struct be_adapter *adapter, - u32 pktsize, u16 numfrags) + u32 pktsize, u16 numfrags, u8 pkt_type) { struct be_drvr_stats *stats = drvr_stats(adapter); @@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_frags += numfrags; stats->be_rx_bytes += pktsize; stats->be_rx_pkts++; + + if (pkt_type == BE_MULTICAST_PACKET) + stats->be_rx_mcast_pkt++; } static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) @@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter, u16 rxq_idx, i, j; u32 pktsize, hdr_len, curr_frag_len, size; u8 *start; + u8 pkt_type; rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); page_info = get_rx_page_info(adapter, rxq_idx); @@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, BUG_ON(j > MAX_SKB_FRAGS); done: - be_rx_stats_update(adapter, pktsize, num_rcvd); + be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type); } /* Process the RX completion indicated by rxcp when GRO is disabled */ @@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; u16 i, rxq_idx = 0, vid, j; u8 vtm; + u8 pkt_type; num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); /* Is it a flush compl that has no data */ @@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); + pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ @@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); } - be_rx_stats_update(adapter, pkt_size, num_rcvd); + be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type); } static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) -- cgit v1.2.3-70-g09d2 From d053de911bff69ba7cdda36d3107c1da0fba7ccd Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 3 Sep 2010 06:23:30 +0000 Subject: be2net: fix a bug in UE detection logic The ONLINE registers can return 0xFFFFFFFF on more than one occassion. On systems that care, reading these registers could lead to problems. So the new code decides that the ASIC has encountered and error by reading the UE_STATUS_LOW/HIGH registers. AND them with the mask values and a non-zero result indicates an error. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 2 +- drivers/net/benet/be_cmds.h | 2 +- drivers/net/benet/be_main.c | 32 ++++++++------------------------ 3 files changed, 10 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 3d305494a60..78f32fe68c0 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -207,7 +207,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); - be_dump_ue(adapter); + be_detect_dump_ue(adapter); return -1; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index bdc10a28cfd..ad1e6fac60c 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, extern int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd); extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); -extern void be_dump_ue(struct be_adapter *adapter); +extern void be_detect_dump_ue(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a5a24e6c773..6eda7a02225 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1750,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) return 1; } -static inline bool be_detect_ue(struct be_adapter *adapter) -{ - u32 online0 = 0, online1 = 0; - - pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0); - - pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1); - - if (!online0 || !online1) { - adapter->ue_detected = true; - dev_err(&adapter->pdev->dev, - "UE Detected!! online0=%d online1=%d\n", - online0, online1); - return true; - } - - return false; -} - -void be_dump_ue(struct be_adapter *adapter) +void be_detect_dump_ue(struct be_adapter *adapter) { u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask; u32 i; @@ -1786,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter) ue_status_lo = (ue_status_lo & (~ue_status_lo_mask)); ue_status_hi = (ue_status_hi & (~ue_status_hi_mask)); + if (ue_status_lo || ue_status_hi) { + adapter->ue_detected = true; + dev_err(&adapter->pdev->dev, "UE Detected!!\n"); + } + if (ue_status_lo) { for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) { if (ue_status_lo & 1) @@ -1821,10 +1807,8 @@ static void be_worker(struct work_struct *work) adapter->rx_post_starved = false; be_post_rx_frags(adapter); } - if (!adapter->ue_detected) { - if (be_detect_ue(adapter)) - be_dump_ue(adapter); - } + if (!adapter->ue_detected) + be_detect_dump_ue(adapter); schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } -- cgit v1.2.3-70-g09d2 From 323f30b361b2e6febb9065ab4a1a5298acb66ac1 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 3 Sep 2010 06:24:13 +0000 Subject: be2net: remove a BUG_ON in be_cmds.c Async notifications other than link status are possible in certain configurations. Remove the BUG_ON in the mcc completion processing path. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 78f32fe68c0..34abcc9403d 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status) while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ - BUG_ON(!is_link_state_evt(compl->flags)); - - /* Interpret compl as a async link evt */ - be_async_link_state_process(adapter, + if (is_link_state_evt(compl->flags)) + be_async_link_state_process(adapter, (struct be_async_event_link_state *) compl); } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { *status = be_mcc_compl_process(adapter, compl); -- cgit v1.2.3-70-g09d2 From c4433be6e19e3680727f3f89c938a22e7b789b43 Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Mon, 6 Sep 2010 05:02:11 +0200 Subject: stmmac: fix sleep inside atomic We cannot use spinlock when kmalloc is invoked with GFP_KERNEL flag because it can sleep. So this patch reviews the usage of spinlock within the stmmac_resume function avoing this bug. Signed-off-by: Giuseppe Cavallaro Reported-by: Jiri Slaby Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index bbb7951b9c4..ea0461eb2db 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev) if (!netif_running(dev)) return 0; - spin_lock(&priv->lock); - if (priv->shutdown) { /* Re-open the interface and re-init the MAC/DMA - and the rings. */ + and the rings (i.e. on hibernation stage) */ stmmac_open(dev); - goto out_resume; + return 0; } + spin_lock(&priv->lock); + /* Power Down bit, into the PM register, is cleared * automatically as soon as a magic packet or a Wake-up frame * is received. Anyway, it's better to manually clear @@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev) netif_start_queue(dev); -out_resume: spin_unlock(&priv->lock); return 0; } -- cgit v1.2.3-70-g09d2 From cb32f2a0d194212e4e750a8cdedcc610c9ca4876 Mon Sep 17 00:00:00 2001 From: Jiri Bohac Date: Thu, 2 Sep 2010 05:45:54 +0000 Subject: bonding: Fix jiffies overflow problems (again) The time_before_eq()/time_after_eq() functions operate on unsigned long and only work if the difference between the two compared values is smaller than half the range of unsigned long (31 bits on i386). Some of the variables (slave->jiffies, dev->trans_start, dev->last_rx) used by bonding store a copy of jiffies and may not be updated for a long time. With HZ=1000, time_before_eq()/time_after_eq() will start giving bad results after ~25 days. jiffies will never be before slave->jiffies, dev->trans_start, dev->last_rx by more than possibly a couple ticks caused by preemption of this code. This allows us to detect/prevent these overflows by replacing time_before_eq()/time_after_eq() with time_in_range(). Signed-off-by: Jiri Bohac Signed-off-by: Jean Delvare Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 56 ++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2cc4cfc3189..3b16f62d560 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * so it can wait */ bond_for_each_slave(bond, slave, i) { + unsigned long trans_start = dev_trans_start(slave->dev); + if (slave->link != BOND_LINK_UP) { - if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) && - time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) { + if (time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + delta_in_ticks) && + time_in_range(jiffies, + slave->dev->last_rx - delta_in_ticks, + slave->dev->last_rx + delta_in_ticks)) { slave->link = BOND_LINK_UP; slave->state = BOND_STATE_ACTIVE; @@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * when the source ip is 0, so don't take the link down * if we don't know our ip yet */ - if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) || - (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) { + if (!time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + 2 * delta_in_ticks) || + !time_in_range(jiffies, + slave->dev->last_rx - delta_in_ticks, + slave->dev->last_rx + 2 * delta_in_ticks)) { slave->link = BOND_LINK_DOWN; slave->state = BOND_STATE_BACKUP; @@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) { struct slave *slave; int i, commit = 0; + unsigned long trans_start; bond_for_each_slave(bond, slave, i) { slave->new_link = BOND_LINK_NOCHANGE; if (slave->link != BOND_LINK_UP) { - if (time_before_eq(jiffies, slave_last_rx(bond, slave) + - delta_in_ticks)) { + if (time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + delta_in_ticks)) { + slave->new_link = BOND_LINK_UP; commit++; } @@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) * active. This avoids bouncing, as the last receive * times need a full ARP monitor cycle to be updated. */ - if (!time_after_eq(jiffies, slave->jiffies + - 2 * delta_in_ticks)) + if (time_in_range(jiffies, + slave->jiffies - delta_in_ticks, + slave->jiffies + 2 * delta_in_ticks)) continue; /* @@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) */ if (slave->state == BOND_STATE_BACKUP && !bond->current_arp_slave && - time_after(jiffies, slave_last_rx(bond, slave) + - 3 * delta_in_ticks)) { + !time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + 3 * delta_in_ticks)) { + slave->new_link = BOND_LINK_DOWN; commit++; } @@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) * - (more than 2*delta since receive AND * the bond has an IP address) */ + trans_start = dev_trans_start(slave->dev); if ((slave->state == BOND_STATE_ACTIVE) && - (time_after_eq(jiffies, dev_trans_start(slave->dev) + - 2 * delta_in_ticks) || - (time_after_eq(jiffies, slave_last_rx(bond, slave) - + 2 * delta_in_ticks)))) { + (!time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + 2 * delta_in_ticks) || + !time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + 2 * delta_in_ticks))) { + slave->new_link = BOND_LINK_DOWN; commit++; } @@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) { struct slave *slave; int i; + unsigned long trans_start; bond_for_each_slave(bond, slave, i) { switch (slave->new_link) { @@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) continue; case BOND_LINK_UP: + trans_start = dev_trans_start(slave->dev); if ((!bond->curr_active_slave && - time_before_eq(jiffies, - dev_trans_start(slave->dev) + - delta_in_ticks)) || + time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + delta_in_ticks)) || bond->curr_active_slave != slave) { slave->link = BOND_LINK_UP; bond->current_arp_slave = NULL; -- cgit v1.2.3-70-g09d2 From 89b12faba4f3441c9457c5278851e8a93ffd008d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 6 Sep 2010 18:28:56 -0700 Subject: 3c59x: Fix deadlock in vortex_error() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a bug introduced in commit de847272149365363a6043a963a6f42fb91566e2 "3c59x: Use fine-grained locks for MII and windowed register access". vortex_interrupt() holds vp->window_lock over multiple register accesses to reduce locking overhead. However it also needs to call vortex_error() sometimes, and that uses the regular functions for access to windowed registers, which will try to acquire window_lock again. Therefore, drop window_lock around the call to vortex_error() and set the window afterward reacquiring the lock. Since vortex_error() may call vortex_rx(), which *does* require its caller to hold window_lock, lift that call up into vortex_interrupt(). This also removes the potential for calling vortex_rx() on a later-generation NIC. Reported-and-tested-by: Jens Schüßler [in Debian's 2.6.32] Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index a045559c81c..85671adae45 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1994,10 +1994,9 @@ vortex_error(struct net_device *dev, int status) } } - if (status & RxEarly) { /* Rx early is unused. */ - vortex_rx(dev); + if (status & RxEarly) /* Rx early is unused. */ iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); - } + if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat; if (vortex_debug > 4) @@ -2298,7 +2297,12 @@ vortex_interrupt(int irq, void *dev_id) if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { if (status == 0xffff) break; + if (status & RxEarly) + vortex_rx(dev); + spin_unlock(&vp->window_lock); vortex_error(dev, status); + spin_lock(&vp->window_lock); + window_set(vp, 7); } if (--work_done < 0) { -- cgit v1.2.3-70-g09d2 From 32737e934a952c1b0c744f2a78d80089d15c7ee3 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Sat, 4 Sep 2010 14:17:59 +0000 Subject: PATCH: b44 Handle RX FIFO overflow better (simplified) This patch is a simplified version of the original patch from James Courtier-Dutton. >From: James Courtier-Dutton >Subject: [PATCH] Fix b44 RX FIFO overflow recovery. >Date: Wednesday, June 30, 2010 - 1:11 pm > >This patch improves the recovery after a RX FIFO overflow on the b44 >Ethernet NIC. >Before it would do a complete chip reset, resulting is loss of link >for a few seconds. >This patch improves this to do recovery in about 20ms without loss of link. > >Signed off by: James@superbug.co.uk Signed-off-by: Mark Lord Signed-off-by: David S. Miller --- drivers/net/b44.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 37617abc164..1e620e287ae 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget) b44_tx(bp); /* spin_unlock(&bp->tx_lock); */ } + if (bp->istat & ISTAT_RFO) { /* fast recovery, in ~20msec */ + bp->istat &= ~ISTAT_RFO; + b44_disable_ints(bp); + ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */ + b44_init_rings(bp); + b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY); + netif_wake_queue(bp->dev); + } + spin_unlock_irqrestore(&bp->lock, flags); work_done = 0; -- cgit v1.2.3-70-g09d2 From de2b96f1212722eb0af80bf9a029d03d8fc673a9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 7 Sep 2010 13:49:44 -0700 Subject: via-velocity: Turn scatter-gather support back off. It causes all kinds of DMA API debugging assertions and all straight-forward attempts to fix it have failed. So turn off SG, and we'll tackle making this work properly in net-next-2.6 Reported-by: Dave Jones Tested-by: Dave Jones Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index fd69095ef6e..f53412368ce 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | - NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG; + NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM; ret = register_netdev(dev); if (ret < 0) -- cgit v1.2.3-70-g09d2 From ee9c5cfad29c8a13199962614b9b16f1c4137ac9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 7 Sep 2010 04:35:19 +0000 Subject: niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL niu_get_ethtool_tcam_all() assumes that its output buffer is the right size, and warns before returning if it is not. However, the output buffer size is under user control and ETHTOOL_GRXCLSRLALL is an unprivileged ethtool command. Therefore this is at least a local denial-of-service vulnerability. Change it to check before writing each entry and to return an error if the buffer is already full. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/niu.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index b9b950845b0..340cbec4894 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7272,32 +7272,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np, struct niu_parent *parent = np->parent; struct niu_tcam_entry *tp; int i, idx, cnt; - u16 n_entries; unsigned long flags; - + int ret = 0; /* put the tcam size here */ nfc->data = tcam_get_size(np); niu_lock_parent(np, flags); - n_entries = nfc->rule_cnt; for (cnt = 0, i = 0; i < nfc->data; i++) { idx = tcam_get_index(np, i); tp = &parent->tcam[idx]; if (!tp->valid) continue; + if (cnt == nfc->rule_cnt) { + ret = -EMSGSIZE; + break; + } rule_locs[cnt] = i; cnt++; } niu_unlock_parent(np, flags); - if (n_entries != cnt) { - /* print warning, this should not happen */ - netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n", - np->parent->index, __func__, n_entries, cnt); - } - - return 0; + return ret; } static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, -- cgit v1.2.3-70-g09d2 From 972c40b5bee429c84ba727f8ac0a08292bc5dc3d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 8 Sep 2010 13:26:55 +0000 Subject: KS8851: Correct RX packet allocation Use netdev_alloc_skb_ip_align() helper and do correct allocation Tested-by: Abraham Arce Signed-off-by: Abraham Arce Signed-off-by: David S. Miller --- drivers/net/ks8851.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index b4fb07a6f13..51919fcd50c 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); - if (rxlen > 0) { - skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8); - if (!skb) { - /* todo - dump frame and move on */ - } + if (rxlen > 4) { + unsigned int rxalign; + + rxlen -= 4; + rxalign = ALIGN(rxlen, 4); + skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign); + if (skb) { - /* two bytes to ensure ip is aligned, and four bytes - * for the status header and 4 bytes of garbage */ - skb_reserve(skb, 2 + 4 + 4); + /* 4 bytes of status header + 4 bytes of + * garbage: we put them before ethernet + * header, so that they are copied, + * but ignored. + */ - rxpkt = skb_put(skb, rxlen - 4) - 8; + rxpkt = skb_put(skb, rxlen) - 8; - /* align the packet length to 4 bytes, and add 4 bytes - * as we're getting the rx status header as well */ - ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8); + ks8851_rdfifo(ks, rxpkt, rxalign + 8); - if (netif_msg_pktdata(ks)) - ks8851_dbg_dumpkkt(ks, rxpkt); + if (netif_msg_pktdata(ks)) + ks8851_dbg_dumpkkt(ks, rxpkt); - skb->protocol = eth_type_trans(skb, ks->netdev); - netif_rx(skb); + skb->protocol = eth_type_trans(skb, ks->netdev); + netif_rx(skb); - ks->netdev->stats.rx_packets++; - ks->netdev->stats.rx_bytes += rxlen - 4; + ks->netdev->stats.rx_packets++; + ks->netdev->stats.rx_bytes += rxlen; + } } ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); -- cgit v1.2.3-70-g09d2 From c9cedbba0fc591e1c0587f838932ca3f3c6fec57 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 8 Sep 2010 07:50:47 +0000 Subject: ipheth: remove incorrect devtype to WWAN The 'wwan' devtype is meant for devices that require preconfiguration and *every* time setup before the ethernet interface can be used, like cellular modems which require a series of setup commands on serial ports or other mechanisms before the ethernet interface will handle packets. As ipheth only requires one-per-hotplug pairing setup with no preconfiguration (like APN, phone #, etc) and the network interface is usable at any time after that initial setup, remove the incorrect devtype wwan. Signed-off-by: Dan Williams Signed-off-by: David S. Miller --- drivers/net/usb/ipheth.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 8ed30fa35d0..b2bcf99e6f0 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -429,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = { .ndo_get_stats = &ipheth_stats, }; -static struct device_type ipheth_type = { - .name = "wwan", -}; - static int ipheth_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -450,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf, netdev->netdev_ops = &ipheth_netdev_ops; netdev->watchdog_timeo = IPHETH_TX_TIMEOUT; - strcpy(netdev->name, "wwan%d"); + strcpy(netdev->name, "eth%d"); dev = netdev_priv(netdev); dev->udev = udev; @@ -500,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf, SET_NETDEV_DEV(netdev, &intf->dev); SET_ETHTOOL_OPS(netdev, &ops); - SET_NETDEV_DEVTYPE(netdev, &ipheth_type); retval = register_netdev(netdev); if (retval) { -- cgit v1.2.3-70-g09d2 From 3429769bc67c7a48b3c01b2452b32171b3450202 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Sep 2010 01:58:10 +0000 Subject: ppp: potential NULL dereference in ppp_mp_explode() Smatch complains because we check whether "pch->chan" is NULL and then dereference it unconditionally on the next line. Partly the reason this bug was introduced is because code was too complicated. I've simplified it a little. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6695a51e09e..736b91703b3 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1314,8 +1314,13 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; i = 0; list_for_each_entry(pch, &ppp->channels, clist) { - navail += pch->avail = (pch->chan != NULL); - pch->speed = pch->chan->speed; + if (pch->chan) { + pch->avail = 1; + navail++; + pch->speed = pch->chan->speed; + } else { + pch->avail = 0; + } if (pch->avail) { if (skb_queue_empty(&pch->file.xq) || !pch->had_frag) { -- cgit v1.2.3-70-g09d2 From ab12811c89e88f2e66746790b1fe4469ccb7bdd9 Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Fri, 10 Sep 2010 11:43:20 +0000 Subject: bonding: correctly process non-linear skbs It was recently brought to my attention that 802.3ad mode bonds would no longer form when using some network hardware after a driver update. After snooping around I realized that the particular hardware was using page-based skbs and found that skb->data did not contain a valid LACPDU as it was not stored there. That explained the inability to form an 802.3ad-based bond. For balance-alb mode bonds this was also an issue as ARPs would not be properly processed. This patch fixes the issue in my tests and should be applied to 2.6.36 and as far back as anyone cares to add it to stable. Thanks to Alexander Duyck and Jesse Brandeburg for the suggestions on this one. Signed-off-by: Andy Gospodarek CC: Alexander Duyck CC: Jesse Brandeburg CC: stable@kerne.org Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 3 +++ drivers/net/bonding/bond_alb.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 822f586d72a..0ddf4c66afe 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) + goto out; + read_lock(&bond->lock); slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), orig_dev); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index c746b331771..26bb118c453 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -362,6 +362,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) + goto out; + if (skb->len < sizeof(struct arp_pkt)) { pr_debug("Packet is too small to be an ARP\n"); goto out; -- cgit v1.2.3-70-g09d2 From fddd91016d16277a32727ad272cf2edd3d309c90 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 13 Sep 2010 22:12:01 +0000 Subject: phylib: fix PAL state machine restart on resume On resume, before starting the PAL state machine, check if the adjust_link() method is well supplied. If not, this would lead to a NULL pointer dereference in the phy_state_machine() function. This scenario can happen if the Ethernet driver call manually the PHY functions instead of using the PAL state machine. The mv643xx_eth driver is a such example. Signed-off-by: Simon Guinot Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6a6b8199a0d..6c58da2b882 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -308,7 +308,7 @@ static int mdio_bus_suspend(struct device *dev) * may call phy routines that try to grab the same lock, and that may * lead to a deadlock. */ - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_stop_machine(phydev); if (!mdio_bus_phy_may_suspend(phydev)) @@ -331,7 +331,7 @@ static int mdio_bus_resume(struct device *dev) return ret; no_resume: - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_start_machine(phydev, NULL); return 0; -- cgit v1.2.3-70-g09d2 From b76dc0546709aef18f123847680108c2fd33f203 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 13 Sep 2010 20:23:12 +0200 Subject: pcmcia pcnet_cs: try setting io_lines to 16 if card setup fails Some pcnet_cs compatible cards require an exact 16-lines match of the ioport areas specified in CIS, but set the "iolines" value in the CIS incorrectly. We can easily work around this issue -- same as we do in serial_cs -- by first trying setting iolines to the CIS-specified value, and then trying a 16-line match. Reported-and-tested-by: Wolfram Sang Hardware-supplied-by: Jochen Frieling CC: netdev@vger.kernel.org Signed-off-by: Dominik Brodowski --- drivers/net/pcmcia/pcnet_cs.c | 139 +++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 49279b0ee52..f9b509a6b09 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - int *has_shmem = priv_data; + int *priv = priv_data; + int try = (*priv & 0x1); int i; cistpl_io_t *io = &cfg->io; @@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, i = p_dev->resource[1]->end = 0; } - *has_shmem = ((cfg->mem.nwin == 1) && - (cfg->mem.win[0].len >= 0x4000)); + *priv &= ((cfg->mem.nwin == 1) && + (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; + p_dev->resource[0]->start = io->win[i].base; p_dev->resource[0]->end = io->win[i].len; - p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + if (!try) + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + else + p_dev->io_lines = 16; if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) return try_io_port(p_dev); - return 0; + return -EINVAL; +} + +static hw_info_t *pcnet_try_config(struct pcmcia_device *link, + int *has_shmem, int try) +{ + struct net_device *dev = link->priv; + hw_info_t *local_hw_info; + pcnet_dev_t *info = PRIV(dev); + int priv = try; + int ret; + + ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); + if (ret) { + dev_warn(&link->dev, "no useable port range found\n"); + return NULL; + } + *has_shmem = (priv & 0x10); + + if (!link->irq) + return NULL; + + if (resource_size(link->resource[1]) == 8) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + if ((link->manf_id == MANFID_IBM) && + (link->card_id == PRODID_IBM_HOME_AND_AWAY)) + link->conf.ConfigIndex |= 0x10; + + ret = pcmcia_request_configuration(link, &link->conf); + if (ret) + return NULL; + + dev->irq = link->irq; + dev->base_addr = link->resource[0]->start; + + if (info->flags & HAS_MISC_REG) { + if ((if_port == 1) || (if_port == 2)) + dev->if_port = if_port; + else + dev_notice(&link->dev, "invalid if_port requested\n"); + } else + dev->if_port = 0; + + if ((link->conf.ConfigBase == 0x03c0) && + (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { + dev_info(&link->dev, + "this is an AX88190 card - use axnet_cs instead.\n"); + return NULL; + } + + local_hw_info = get_hwinfo(link); + if (!local_hw_info) + local_hw_info = get_prom(link); + if (!local_hw_info) + local_hw_info = get_dl10019(link); + if (!local_hw_info) + local_hw_info = get_ax88190(link); + if (!local_hw_info) + local_hw_info = get_hwired(link); + + return local_hw_info; } static int pcnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); - int ret, start_pg, stop_pg, cm_offset; + int start_pg, stop_pg, cm_offset; int has_shmem = 0; hw_info_t *local_hw_info; dev_dbg(&link->dev, "pcnet_config\n"); - ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); - if (ret) - goto failed; - - if (!link->irq) - goto failed; - - if (resource_size(link->resource[1]) == 8) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - if ((link->manf_id == MANFID_IBM) && - (link->card_id == PRODID_IBM_HOME_AND_AWAY)) - link->conf.ConfigIndex |= 0x10; - - ret = pcmcia_request_configuration(link, &link->conf); - if (ret) - goto failed; - dev->irq = link->irq; - dev->base_addr = link->resource[0]->start; - if (info->flags & HAS_MISC_REG) { - if ((if_port == 1) || (if_port == 2)) - dev->if_port = if_port; - else - printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); - } else { - dev->if_port = 0; - } - - if ((link->conf.ConfigBase == 0x03c0) && - (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { - printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); - printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); - goto failed; - } - - local_hw_info = get_hwinfo(link); - if (local_hw_info == NULL) - local_hw_info = get_prom(link); - if (local_hw_info == NULL) - local_hw_info = get_dl10019(link); - if (local_hw_info == NULL) - local_hw_info = get_ax88190(link); - if (local_hw_info == NULL) - local_hw_info = get_hwired(link); - - if (local_hw_info == NULL) { - printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" - " address for io base %#3lx\n", dev->base_addr); - goto failed; + local_hw_info = pcnet_try_config(link, &has_shmem, 0); + if (!local_hw_info) { + /* check whether forcing io_lines to 16 helps... */ + pcmcia_disable_device(link); + local_hw_info = pcnet_try_config(link, &has_shmem, 1); + if (local_hw_info == NULL) { + dev_notice(&link->dev, "unable to read hardware net" + " address for io base %#3lx\n", dev->base_addr); + goto failed; + } } info->flags = local_hw_info->flags; -- cgit v1.2.3-70-g09d2 From 84176b7b56704580e008e6cb820dd4ccf622a1fd Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Wed, 15 Sep 2010 00:58:46 +0000 Subject: 3c59x: Remove atomic context inside vortex_{set|get}_wol There is no need to use spinlocks in vortex_{set|get}_wol. This also fixes a bug: [ 254.214993] 3c59x 0000:00:0d.0: PME# enabled [ 254.215021] BUG: sleeping function called from invalid context at kernel/mutex.c:94 [ 254.215030] in_atomic(): 0, irqs_disabled(): 1, pid: 4875, name: ethtool [ 254.215042] Pid: 4875, comm: ethtool Tainted: G W 2.6.36-rc3+ #7 [ 254.215049] Call Trace: [ 254.215050] [] __might_sleep+0xb1/0xb6 [ 254.215050] [] mutex_lock+0x17/0x30 [ 254.215050] [] acpi_enable_wakeup_device_power+0x2b/0xb1 [ 254.215050] [] acpi_pm_device_sleep_wake+0x42/0x7f [ 254.215050] [] acpi_pci_sleep_wake+0x5d/0x63 [ 254.215050] [] platform_pci_sleep_wake+0x1d/0x20 [ 254.215050] [] __pci_enable_wake+0x90/0xd0 [ 254.215050] [] acpi_set_WOL+0x8e/0xf5 [3c59x] [ 254.215050] [] vortex_set_wol+0x4e/0x5e [3c59x] [ 254.215050] [] dev_ethtool+0x1cf/0xb61 [ 254.215050] [] ? debug_mutex_free_waiter+0x45/0x4a [ 254.215050] [] ? __mutex_lock_common+0x204/0x20e [ 254.215050] [] ? __mutex_lock_slowpath+0x12/0x15 [ 254.215050] [] ? mutex_lock+0x23/0x30 [ 254.215050] [] dev_ioctl+0x42c/0x533 [ 254.215050] [] ? _cond_resched+0x8/0x1c [ 254.215050] [] ? lock_page+0x1c/0x30 [ 254.215050] [] ? page_address+0x15/0x7c [ 254.215050] [] ? filemap_fault+0x187/0x2c4 [ 254.215050] [] sock_ioctl+0x1d4/0x1e0 [ 254.215050] [] ? sock_ioctl+0x0/0x1e0 [ 254.215050] [] vfs_ioctl+0x19/0x33 [ 254.215050] [] do_vfs_ioctl+0x424/0x46f [ 254.215050] [] ? selinux_file_ioctl+0x3c/0x40 [ 254.215050] [] sys_ioctl+0x40/0x5a [ 254.215050] [] sysenter_do_call+0x12/0x22 vortex_set_wol protected with a spinlock, but nested acpi_set_WOL acquires a mutex inside atomic context. Ethtool operations are already serialized by RTNL mutex, so it is safe to drop the locks. Signed-off-by: Denis Kirjanov Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 85671adae45..fa42103b287 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -635,6 +635,9 @@ struct vortex_private { must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ large_frames:1, /* accept large frames */ handling_irq:1; /* private in_irq indicator */ + /* {get|set}_wol operations are already serialized by rtnl. + * no additional locking is required for the enable_wol and acpi_set_WOL() + */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -2939,13 +2942,11 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); - spin_lock_irq(&vp->lock); wol->supported = WAKE_MAGIC; wol->wolopts = 0; if (vp->enable_wol) wol->wolopts |= WAKE_MAGIC; - spin_unlock_irq(&vp->lock); } static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) @@ -2954,13 +2955,11 @@ static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; - spin_lock_irq(&vp->lock); if (wol->wolopts & WAKE_MAGIC) vp->enable_wol = 1; else vp->enable_wol = 0; acpi_set_WOL(dev); - spin_unlock_irq(&vp->lock); return 0; } -- cgit v1.2.3-70-g09d2 From 801e147cde02f04b5c2f42764cd43a89fc7400a2 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 14 Sep 2010 11:57:11 +0000 Subject: r8169: Handle rxfifo errors on 8168 chips The Thinkpad X100e seems to have some odd behaviour when the display is powered off - the onboard r8169 starts generating rxfifo overflow errors. The root cause of this has not yet been identified and may well be a hardware design bug on the platform, but r8169 should be more resiliant to this. This patch enables the rxfifo interrupt on 8168 devices and removes the MAC version check in the interrupt handler, and the machine no longer crashes when under network load while the screen turns off. Signed-off-by: Matthew Garrett Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/r8169.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 078bbf4e6f1..a0da4a17b02 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2934,7 +2934,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8168, .region = 2, .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | + .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, @@ -4625,8 +4625,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) } /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + if (unlikely(status & RxFIFOOver)) { netif_stop_queue(dev); rtl8169_tx_timeout(dev); break; -- cgit v1.2.3-70-g09d2 From 7011e660938fc44ed86319c18a5954e95a82ab3e Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:28 +0000 Subject: drivers/net/usb/hso.c: prevent reading uninitialized memory Fixed formatting (tabs and line breaks). The TIOCGICOUNT device ioctl allows unprivileged users to read uninitialized stack memory, because the "reserved" member of the serial_icounter_struct struct declared on the stack in hso_get_count() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller --- drivers/net/usb/hso.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6efca66b876..1cd752f9a6e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1652,6 +1652,8 @@ static int hso_get_count(struct hso_serial *serial, struct uart_icount cnow; struct hso_tiocmget *tiocmget = serial->tiocmget; + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + if (!tiocmget) return -ENOENT; spin_lock_irq(&serial->serial_lock); -- cgit v1.2.3-70-g09d2 From 44467187dc22fdd33a1a06ea0ba86ce20be3fe3c Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:04 +0000 Subject: drivers/net/eql.c: prevent reading uninitialized stack memory Fixed formatting (tabs and line breaks). The EQL_GETMASTRCFG device ioctl allows unprivileged users to read 16 bytes of uninitialized stack memory, because the "master_name" member of the master_config_t struct declared on the stack in eql_g_master_cfg() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller --- drivers/net/eql.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/eql.c b/drivers/net/eql.c index dda2c7944da..0cb1cf9cf4b 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -555,6 +555,8 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp) equalizer_t *eql; master_config_t mc; + memset(&mc, 0, sizeof(master_config_t)); + if (eql_is_master(dev)) { eql = netdev_priv(dev); mc.max_slaves = eql->max_slaves; -- cgit v1.2.3-70-g09d2 From 49c37c0334a9b85d30ab3d6b5d1acb05ef2ef6de Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Wed, 15 Sep 2010 11:43:12 +0000 Subject: drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack memory Fixed formatting (tabs and line breaks). The CHELSIO_GET_QSET_NUM device ioctl allows unprivileged users to read 4 bytes of uninitialized stack memory, because the "addr" member of the ch_reg struct declared on the stack in cxgb_extension_ioctl() is not altered or zeroed before being copied back to the user. This patch takes care of it. Signed-off-by: Dan Rosenberg Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index ad19585d960..f208712c0b9 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2296,6 +2296,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) case CHELSIO_GET_QSET_NUM:{ struct ch_reg edata; + memset(&edata, 0, sizeof(struct ch_reg)); + edata.cmd = CHELSIO_GET_QSET_NUM; edata.val = pi->nqsets; if (copy_to_user(useraddr, &edata, sizeof(edata))) -- cgit v1.2.3-70-g09d2 From 7acc7c683a747689aaaaad4fce1683fc3f85e552 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 8 Sep 2010 08:30:20 -0700 Subject: iwlwifi: do not perferm force reset while doing scan When uCode error condition detected, driver try to perform either rf reset or firmware reload in order bring device back to working condition. If rf reset is required and scan is in process, there is no need to issue rf reset since scan already reset the rf. If firmware reload is required and scan is in process, skip the reload request. There is a possibility firmware reload during scan cause problem. [ 485.804046] WARNING: at net/mac80211/main.c:310 ieee80211_restart_hw+0x28/0x62() [ 485.804049] Hardware name: Latitude E6400 [ 485.804052] ieee80211_restart_hw called with hardware scan in progress [ 485.804054] Modules linked in: iwlagn iwlcore bnep sco rfcomm l2cap crc16 bluetooth [last unloaded: iwlcore] [ 485.804069] Pid: 812, comm: kworker/u:3 Tainted: G W 2.6.36-rc3-wl+ #74 [ 485.804072] Call Trace: [ 485.804079] [] warn_slowpath_common+0x60/0x75 [ 485.804084] [] warn_slowpath_fmt+0x26/0x2a [ 485.804089] [] ieee80211_restart_hw+0x28/0x62 [ 485.804102] [] iwl_bg_restart+0x113/0x150 [iwlagn] [ 485.804108] [] process_one_work+0x181/0x25c [ 485.804119] [] ? iwl_bg_restart+0x0/0x150 [iwlagn] [ 485.804124] [] worker_thread+0xf9/0x1f2 [ 485.804128] [] ? worker_thread+0x0/0x1f2 [ 485.804133] [] kthread+0x64/0x69 [ 485.804137] [] ? kthread+0x0/0x69 [ 485.804141] [] kernel_thread_helper+0x6/0x10 [ 485.804145] ---[ end trace 3d4ebdc02d524bbb ]--- [ 485.804148] WG> 1 [ 485.804153] Pid: 812, comm: kworker/u:3 Tainted: G W 2.6.36-rc3-wl+ #74 [ 485.804156] Call Trace: [ 485.804161] [] ? ieee80211_restart_hw+0x5c/0x62 [ 485.804172] [] iwl_bg_restart+0x118/0x150 [iwlagn] [ 485.804177] [] process_one_work+0x181/0x25c [ 485.804188] [] ? iwl_bg_restart+0x0/0x150 [iwlagn] [ 485.804192] [] worker_thread+0xf9/0x1f2 [ 485.804197] [] ? worker_thread+0x0/0x1f2 [ 485.804201] [] kthread+0x64/0x69 [ 485.804205] [] ? kthread+0x0/0x69 [ 485.804209] [] kernel_thread_helper+0x6/0x10 Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 07dbc279644..e23c4060a0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2613,6 +2613,11 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_INFO(priv, "scan in progress.\n"); + return -EINVAL; + } + if (mode >= IWL_MAX_FORCE_RESET) { IWL_DEBUG_INFO(priv, "invalid reset request.\n"); return -EINVAL; -- cgit v1.2.3-70-g09d2 From 04746ff1289f75af26af279eb4b0b3e231677ee4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Sep 2010 22:58:08 -0700 Subject: qlcnic: dont assume NET_IP_ALIGN is 2 qlcnic driver allocates rx skbs and gives to hardware too bytes of extra storage, allowing for corruption of kernel data. NET_IP_ALIGN being 0 on some platforms (including x86), drivers should not assume it's 2. rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; ... skb = dev_alloc_skb(rds_ring->skb_size); skb_reserve(skb, 2); pci_map_single(pdev, skb->data, rds_ring->dma_size, PCI_DMA_FROMDEVICE); (and rds_ring->skb_size == rds_ring->dma_size) -> bug Because of extra alignment (1500 + 32) -> four extra bytes are available before the struct skb_shared_info, so corruption is not noticed. Note: this driver could use netdev_alloc_skb_ip_align() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 75ba744b173..60ab753f809 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1316,7 +1316,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, return -ENOMEM; } - skb_reserve(skb, 2); + skb_reserve(skb, NET_IP_ALIGN); dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, PCI_DMA_FROMDEVICE); -- cgit v1.2.3-70-g09d2 From 8df8fd27123054b02007361bd5483775db84b4a8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 Sep 2010 02:28:59 +0000 Subject: qlcnic: dont set skb->truesize skb->truesize is set in core network. Dont change it unless dealing with fragments. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_init.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 60ab753f809..2c7cf0b6481 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1404,7 +1404,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1466,8 +1465,6 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -1700,8 +1697,6 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); - if (!qlcnic_check_loopback_buff(skb->data)) adapter->diag_cnt++; -- cgit v1.2.3-70-g09d2 From 7e96dc7045bff8758804b047c0dfb6868f182500 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 Sep 2010 13:04:04 -0700 Subject: netxen: dont set skb->truesize skb->truesize is set in core network. Dont change it unless dealing with fragments. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_init.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index cabae7bb1fc..b075a35b85d 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1540,7 +1540,6 @@ netxen_process_rcv(struct netxen_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1602,8 +1601,6 @@ netxen_process_lro(struct netxen_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); -- cgit v1.2.3-70-g09d2 From ec5a32f67c603b11d68eb283d94eb89a4f6cfce1 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Wed, 22 Sep 2010 10:41:58 +0000 Subject: atl1: fix resume adapter->cmb.cmb is initialized when the device is opened and freed when it's closed. Accessing it unconditionally during resume results either in a crash (NULL pointer dereference, when the interface has not been opened yet) or data corruption (when the interface has been used and brought down adapter->cmb.cmb points to a deallocated memory area). Cc: stable@kernel.org Signed-off-by: Luca Tettamanti Acked-by: Chris Snook Signed-off-by: David S. Miller --- drivers/net/atlx/atl1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 63b9ba0cc67..bbd6e3009be 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2847,10 +2847,11 @@ static int atl1_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); atl1_reset_hw(&adapter->hw); - adapter->cmb.cmb->int_stats = 0; - if (netif_running(netdev)) + if (netif_running(netdev)) { + adapter->cmb.cmb->int_stats = 0; atl1_up(adapter); + } netif_device_attach(netdev); return 0; -- cgit v1.2.3-70-g09d2 From 3f5a2a713aad28480d86b0add00c68484b54febc Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Wed, 22 Sep 2010 10:42:31 +0000 Subject: atl1: zero out CMB and SBM in atl1_free_ring_resources They are allocated in atl1_setup_ring_resources, zero out the pointers in atl1_free_ring_resources (like the other resources). Signed-off-by: Luca Tettamanti Acked-by: Chris Snook Signed-off-by: David S. Miller --- drivers/net/atlx/atl1.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index bbd6e3009be..c73be284831 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -1251,6 +1251,12 @@ static void atl1_free_ring_resources(struct atl1_adapter *adapter) rrd_ring->desc = NULL; rrd_ring->dma = 0; + + adapter->cmb.dma = 0; + adapter->cmb.cmb = NULL; + + adapter->smb.dma = 0; + adapter->smb.smb = NULL; } static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) -- cgit v1.2.3-70-g09d2 From 8395ae8303255b31a8625035fc98391c88b0c257 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:15:08 +0000 Subject: e1000e: 82577/8/9 issues with device in Sx When going to Sx, disable gigabit in PHY (e1000_oem_bits_config_ich8lan) in addition to the MAC before configuring PHY wakeup otherwise the PHY configuration writes might be missed. Also write the LED configuration and SMBus address to the PHY registers (e1000_oem_bits_config_ich8lan and e1000_write_smbus_addr, respectively). The reset is no longer needed since re-auto-negotiation is forced in e1000_oem_bits_config_ich8lan and leaving it in causes issues with auto-negotiating the link. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 47 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 63930d12711..822de4830c6 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -125,6 +125,7 @@ /* SMBus Address Phy Register */ #define HV_SMB_ADDR PHY_REG(768, 26) +#define HV_SMB_ADDR_MASK 0x007F #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 @@ -894,6 +895,34 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? 0 : E1000_BLK_PHY_RESET; } +/** + * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states + * @hw: pointer to the HW structure + * + * Assumes semaphore already acquired. + * + **/ +static s32 e1000_write_smbus_addr(struct e1000_hw *hw) +{ + u16 phy_data; + u32 strap = er32(STRAP); + s32 ret_val = 0; + + strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; + + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~HV_SMB_ADDR_MASK; + phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); + phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); + +out: + return ret_val; +} + /** * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure @@ -970,12 +999,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) * When both NVM bits are cleared, SW will configure * them instead. */ - data = er32(STRAP); - data &= E1000_STRAP_SMBUS_ADDRESS_MASK; - reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; - reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, - reg_data); + ret_val = e1000_write_smbus_addr(hw); if (ret_val) goto out; @@ -3460,13 +3484,20 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; + s32 ret_val; phy_ctrl = er32(PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); - if (hw->mac.type >= e1000_pchlan) - e1000_phy_hw_reset_ich8lan(hw); + if (hw->mac.type >= e1000_pchlan) { + e1000_oem_bits_config_ich8lan(hw, true); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; + e1000_write_smbus_addr(hw); + hw->phy.ops.release(hw); + } } /** -- cgit v1.2.3-70-g09d2 From 87fb7410cd8d4396dee0155526568645adba3b99 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:15:33 +0000 Subject: e1000e: 82579 SMBus address and LEDs incorrect after device reset Since the hardware is prevented from performing automatic PHY configuration (the driver does it instead), the OEM_WRITE_ENABLE bit in the EXTCNF_CTRL register will not get cleared preventing the SMBus address and the LED configuration to be written to the PHY registers. On 82579, do not check the OEM_WRITE_ENABLE bit. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 822de4830c6..fc8c3cef052 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -990,9 +990,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - ((hw->mac.type == e1000_pchlan) || - (hw->mac.type == e1000_pch2lan))) { + if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && + (hw->mac.type == e1000_pchlan)) || + (hw->mac.type == e1000_pch2lan)) { /* * HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. -- cgit v1.2.3-70-g09d2 From 5f3eed6fe0e36e4b56c8dd9160241a868ee0de2a Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:15:54 +0000 Subject: e1000e: 82566DC fails to get link Two recent patches to cleanup the reset[1] and initial PHY configuration[2] code paths for ICH/PCH devices inadvertently left out a 10msec delay and device ID check respectively which are necessary for the 82566DC (device id 0x104b) to be configured properly, otherwise it will not get link. [1] commit e98cac447cc1cc418dff1d610a5c79c4f2bdec7f [2] commit 3f0c16e84438d657d29446f85fe375794a93f159 CC: stable@kernel.org Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index fc8c3cef052..6f9cb0d44d3 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -932,7 +932,6 @@ out: **/ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) { - struct e1000_adapter *adapter = hw->adapter; struct e1000_phy_info *phy = &hw->phy; u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val = 0; @@ -950,7 +949,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) if (phy->type != e1000_phy_igp_3) return ret_val; - if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) { + if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) || + (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) { sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; break; } @@ -1626,6 +1626,9 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) if (e1000_check_reset_block(hw)) goto out; + /* Allow time for h/w to get to quiescent state after reset */ + msleep(10); + /* Perform any necessary post-reset workarounds */ switch (hw->mac.type) { case e1000_pchlan: -- cgit v1.2.3-70-g09d2 From 831bd2e6a6c09588fdde453ecb858f050ac1b942 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:16:18 +0000 Subject: e1000e: 82579 unaccounted missed packets On 82579, there is a hardware bug that can cause received packets to not get transferred from the PHY to the MAC due to K1 (a power saving feature of the PHY-MAC interconnect similar to ASPM L1). Since the MAC controls the accounting of missed packets, these will go unnoticed. Workaround the issue by setting the K1 beacon duration according to the link speed. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/hw.h | 1 + drivers/net/e1000e/ich8lan.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 66ed08f726f..ba302a5c2c3 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -57,6 +57,7 @@ enum e1e_registers { E1000_SCTL = 0x00024, /* SerDes Control - RW */ E1000_FCAL = 0x00028, /* Flow Control Address Low - RW */ E1000_FCAH = 0x0002C, /* Flow Control Address High -RW */ + E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */ E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */ E1000_FCT = 0x00030, /* Flow Control Type - RW */ E1000_VET = 0x00038, /* VLAN Ether Type - RW */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 6f9cb0d44d3..89b1e1aea52 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -105,6 +105,10 @@ #define E1000_FEXTNVM_SW_CONFIG 1 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */ +#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 + #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -238,6 +242,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -653,6 +658,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) goto out; } + if (hw->mac.type == e1000_pch2lan) { + ret_val = e1000_k1_workaround_lv(hw); + if (ret_val) + goto out; + } + /* * Check if there was DownShift, must be checked * immediately after link-up @@ -1582,6 +1593,43 @@ out: return ret_val; } +/** + * e1000_k1_gig_workaround_lv - K1 Si workaround + * @hw: pointer to the HW structure + * + * Workaround to set the K1 beacon duration for 82579 parts + **/ +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 status_reg = 0; + u32 mac_reg; + + if (hw->mac.type != e1000_pch2lan) + goto out; + + /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); + if (ret_val) + goto out; + + if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) + == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + + if (status_reg & HV_M_STATUS_SPEED_1000) + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + else + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; + + ew32(FEXTNVM4, mac_reg); + } + +out: + return ret_val; +} + /** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure -- cgit v1.2.3-70-g09d2 From a1ce647378c0262fe72757f989e961b2de6460a5 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:16:40 +0000 Subject: e1000e: 82579 jumbo frame workaround causing CRC errors The subject workaround was causing CRC errors due to writing the wrong register with updates of the RCTL register. It was also found that the workaround function which modifies the RCTL register was being called in the middle of a read-modify-write operation of the RCTL register, so the function call has been moved appropriately. Lastly, jumbo frames must not be allowed when CRC stripping is disabled by a module parameter because the workaround requires the CRC be stripped. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 12 +----------- drivers/net/e1000e/netdev.c | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 89b1e1aea52..bb346ae3d9a 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1475,10 +1475,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Enable jumbo frame workaround in the PHY */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); data |= (0x37 << 5); @@ -1487,7 +1483,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); data &= ~(1 << 13); - data |= (1 << 12); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) goto out; @@ -1512,7 +1507,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) mac_reg = er32(RCTL); mac_reg &= ~E1000_RCTL_SECRC; - ew32(FFLT_DBG, mac_reg); + ew32(RCTL, mac_reg); ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, @@ -1538,17 +1533,12 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Write PHY register values back to h/w defaults */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); if (ret_val) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); - data &= ~(1 << 12); data |= (1 << 13); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2b8ef44bd2b..e561d15c3eb 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2704,6 +2704,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) u32 psrctl = 0; u32 pages = 0; + /* Workaround Si errata on 82579 - configure jumbo frame flow */ + if (hw->mac.type == e1000_pch2lan) { + s32 ret_val; + + if (adapter->netdev->mtu > ETH_DATA_LEN) + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); + else + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); + } + /* Program MC offset vector base */ rctl = er32(RCTL); rctl &= ~(3 << E1000_RCTL_MO_SHIFT); @@ -2744,16 +2754,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) e1e_wphy(hw, 22, phy_data); } - /* Workaround Si errata on 82579 - configure jumbo frame flow */ - if (hw->mac.type == e1000_pch2lan) { - s32 ret_val; - - if (rctl & E1000_RCTL_LPE) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - } - /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -4833,6 +4833,15 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } + /* Jumbo frame workaround on 82579 requires CRC be stripped */ + if ((adapter->hw.mac.type == e1000_pch2lan) && + !(adapter->flags2 & FLAG2_CRC_STRIPPING) && + (new_mtu > ETH_DATA_LEN)) { + e_err("Jumbo Frames not supported on 82579 when CRC " + "stripping is disabled.\n"); + return -EINVAL; + } + /* 82573 Errata 17 */ if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_82574)) && -- cgit v1.2.3-70-g09d2 From 605c82bab5abe0816e5e32716875c245f89f39da Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 22 Sep 2010 17:17:01 +0000 Subject: e1000e: 82579 do not gate auto config of PHY by hardware during nominal use For non-managed versions of 82579, set the bit that prevents the hardware from automatically configuring the PHY after resets only when the driver performs a reset, clear the bit after resets. This is so the hardware can configure the PHY automatically when the part is reset in a manner that is not controlled by the driver (e.g. in a virtual environment via PCI FLR) otherwise the PHY will be mis-configured causing issues such as failing to link at 1000Mbps. For managed versions of 82579, keep the previous behavior since the manageability firmware will handle the PHY configuration. Signed-off-by: Bruce Allan Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 77 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index bb346ae3d9a..57b5435599a 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -243,6 +243,7 @@ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -278,7 +279,7 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - u32 ctrl; + u32 ctrl, fwsm; s32 ret_val = 0; phy->addr = 1; @@ -300,7 +301,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) * disabled, then toggle the LANPHYPC Value bit to force * the interconnect to PCIe mode. */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + fwsm = er32(FWSM); + if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) { ctrl = er32(CTRL); ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; @@ -309,6 +311,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; ew32(CTRL, ctrl); msleep(50); + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if (hw->mac.type == e1000_pch2lan) + e1000_gate_hw_phy_config_ich8lan(hw, true); } /* @@ -321,6 +330,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) if (ret_val) goto out; + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + phy->id = e1000_phy_unknown; ret_val = e1000e_get_phy_id(hw); if (ret_val) @@ -567,13 +583,10 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - /* Disable PHY configuration by hardware, config by software */ - if (mac->type == e1000_pch2lan) { - u32 extcnf_ctrl = er32(EXTCNF_CTRL); - - extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - } + /* Gate automatic PHY configuration by hardware on managed 82579 */ + if ((mac->type == e1000_pch2lan) && + (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); return 0; } @@ -1620,6 +1633,32 @@ out: return ret_val; } +/** + * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware + * @hw: pointer to the HW structure + * @gate: boolean set to true to gate, false to ungate + * + * Gate/ungate the automatic PHY configuration via hardware; perform + * the configuration via software instead. + **/ +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) +{ + u32 extcnf_ctrl; + + if (hw->mac.type != e1000_pch2lan) + return; + + extcnf_ctrl = er32(EXTCNF_CTRL); + + if (gate) + extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; + else + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; + + ew32(EXTCNF_CTRL, extcnf_ctrl); + return; +} + /** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure @@ -1695,6 +1734,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, true); + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + out: return ret_val; } @@ -1711,6 +1757,11 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { s32 ret_val = 0; + /* Gate automatic PHY configuration by hardware on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); + ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) goto out; @@ -2975,6 +3026,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); } ret_val = e1000_acquire_swflag_ich8lan(hw); e_dbg("Issuing a global reset to ich8lan\n"); -- cgit v1.2.3-70-g09d2 From e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 23 Sep 2010 10:59:18 +0000 Subject: de2104x: disable autonegotiation on broken hardware At least on older 21041-AA chips (mine is rev. 11), TP duplex autonegotiation causes the card not to work at all (link is up but no packets are transmitted). de4x5 disables autonegotiation completely. But it seems to work on newer (21041-PA rev. 21) so disable it only on rev<20 chips. Signed-off-by: Ondrej Zary Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 5efa57757a2..9d6b7e9c7a6 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -364,6 +364,8 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; +/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ +static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; @@ -1911,8 +1913,14 @@ fill_defaults: for (i = 0; i < DE_MAX_MEDIA; i++) { if (de->media[i].csr13 == 0xffff) de->media[i].csr13 = t21041_csr13[i]; - if (de->media[i].csr14 == 0xffff) - de->media[i].csr14 = t21041_csr14[i]; + if (de->media[i].csr14 == 0xffff) { + /* autonegotiation is broken at least on some chip + revisions - rev. 0x21 works, 0x11 does not */ + if (de->pdev->revision < 0x20) + de->media[i].csr14 = t21041_csr14_brk[i]; + else + de->media[i].csr14 = t21041_csr14[i]; + } if (de->media[i].csr15 == 0xffff) de->media[i].csr15 = t21041_csr15[i]; } -- cgit v1.2.3-70-g09d2 From b0255a02351b00ca55f4eb2588d05a5db9dd1a58 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 24 Sep 2010 23:57:02 +0000 Subject: de2104x: fix power management At least my 21041 cards come out of suspend with bus mastering disabled so they did not work after resume(no data transferred). After adding pci_set_master(), the driver oopsed immediately on resume - because de_clean_rings() is called on suspend but de_init_rings() call was missing in resume. Also disable link (reset SIA) before sleep (de4x5 does this too). Signed-off-by: Ondrej Zary Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 9d6b7e9c7a6..a0be7c28c58 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1231,6 +1231,7 @@ static void de_adapter_sleep (struct de_private *de) if (de->de21040) return; + dw32(CSR13, 0); /* Reset phy */ pci_read_config_dword(de->pdev, PCIPM, &pmctl); pmctl |= PM_Sleep; pci_write_config_dword(de->pdev, PCIPM, pmctl); @@ -2166,6 +2167,8 @@ static int de_resume (struct pci_dev *pdev) dev_err(&dev->dev, "pci_enable_device failed in resume\n"); goto out; } + pci_set_master(pdev); + de_init_rings(de); de_init_hw(de); out_attach: netif_device_attach(dev); -- cgit v1.2.3-70-g09d2 From ca9a783575d2affed30ef27a3427a7705527ddac Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sat, 25 Sep 2010 10:39:17 +0000 Subject: de2104x: fix TP link detection Compex FreedomLine 32 PnP-PCI2 cards have only TP and BNC connectors but the SROM contains AUI port too. When TP loses link, the driver switches to non-existing AUI port (which reports that carrier is always present). Connecting TP back generates LinkPass interrupt but de_media_interrupt() is broken - it only updates the link state of currently connected media, ignoring the fact that LinkPass and LinkFail bits of MacStatus register belong to the TP port only (the chip documentation says that). This patch changes de_media_interrupt() to switch media to TP when link goes up (and media type is not locked) and also to update the link state only when the TP port is used. Also the NonselPortActive (and also SelPortActive) bits of SIAStatus register need to be cleared (by writing 1) after reading or they're useless. Signed-off-by: Ondrej Zary Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index a0be7c28c58..9124c5c638d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -243,6 +243,7 @@ enum { NWayState = (1 << 14) | (1 << 13) | (1 << 12), NWayRestart = (1 << 12), NonselPortActive = (1 << 9), + SelPortActive = (1 << 8), LinkFailStatus = (1 << 2), NetCxnErr = (1 << 1), }; @@ -1066,6 +1067,9 @@ static void de21041_media_timer (unsigned long data) unsigned int carrier; unsigned long flags; + /* clear port active bits */ + dw32(SIAStatus, NonselPortActive | SelPortActive); + carrier = (status & NetCxnErr) ? 0 : 1; if (carrier) { @@ -1160,14 +1164,29 @@ no_link_yet: static void de_media_interrupt (struct de_private *de, u32 status) { if (status & LinkPass) { + /* Ignore if current media is AUI or BNC and we can't use TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC) && + (de->media_lock || + !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))) + return; + /* If current media is not TP, change it to TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC)) { + de->media_type = DE_MEDIA_TP_AUTO; + de_stop_rxtx(de); + de_set_media(de); + de_start_rxtx(de); + } de_link_up(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); return; } BUG_ON(!(status & LinkFail)); - - if (netif_carrier_ok(de->dev)) { + /* Mark the link as down only if current media is TP */ + if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI && + de->media_type != DE_MEDIA_BNC) { de_link_down(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); } -- cgit v1.2.3-70-g09d2 From 62038e4a146b97352d5911e6ede36c58d4187c3e Mon Sep 17 00:00:00 2001 From: Vincent Stehlé Date: Sun, 26 Sep 2010 18:50:05 -0700 Subject: smsc911x: Add MODULE_ALIAS() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables auto loading for the smsc911x ethernet driver. Signed-off-by: Vincent Stehlé Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 0909ae934ad..8150ba15411 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -58,6 +58,7 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(SMSC_DRV_VERSION); +MODULE_ALIAS("platform:smsc911x"); #if USE_DEBUG > 0 static int debug = 16; -- cgit v1.2.3-70-g09d2 From 52933f052186877afd218aef7a1b2dbdb010939f Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Sat, 25 Sep 2010 23:58:00 +0000 Subject: ibm_newemac: use free_netdev(netdev) instead of kfree() Freeing netdev without free_netdev() leads to net, tx leaks. I might lead to dereferencing freed pointer. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) @@ struct net_device* dev; @@ -kfree(dev) +free_netdev(dev) Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 3506fd6ad72..519e19e2395 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2928,7 +2928,7 @@ static int __devinit emac_probe(struct platform_device *ofdev, if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); err_free: - kfree(ndev); + free_netdev(ndev); err_gone: /* if we were on the bootlist, remove us as we won't show up and * wake up all waiters to notify them in case they were waiting @@ -2971,7 +2971,7 @@ static int __devexit emac_remove(struct platform_device *ofdev) if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); - kfree(dev->ndev); + free_netdev(dev->ndev); return 0; } -- cgit v1.2.3-70-g09d2 From 22138d307329e1968fc698821095b87c2fd5de12 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Sat, 25 Sep 2010 23:58:03 +0000 Subject: rionet: use free_netdev(netdev) instead of kfree() Freeing netdev without free_netdev() leads to net, tx leaks. I might lead to dereferencing freed pointer. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) @@ struct net_device* dev; @@ -kfree(dev) +free_netdev(dev) Signed-off-by: David S. Miller --- drivers/net/rionet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 07eb884ff98..44150f2f7bf 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -384,7 +384,7 @@ static void rionet_remove(struct rio_dev *rdev) free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0); unregister_netdev(ndev); - kfree(ndev); + free_netdev(ndev); list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { list_del(&peer->node); -- cgit v1.2.3-70-g09d2 From 8d879de89807d82bc4cc3e9d73609b874fa9458c Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Sat, 25 Sep 2010 23:58:06 +0000 Subject: sgiseeq: use free_netdev(netdev) instead of kfree() Freeing netdev without free_netdev() leads to net, tx leaks. I might lead to dereferencing freed pointer. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) @@ struct net_device* dev; @@ -kfree(dev) +free_netdev(dev) Signed-off-by: David S. Miller --- drivers/net/sgiseeq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index cc4bd8c65f8..9265315baa0 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -804,7 +804,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) err_out_free_page: free_page((unsigned long) sp->srings); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out: return err; -- cgit v1.2.3-70-g09d2 From 3fd6c88ef875a14740801ebfc6b6e4e064a1cdd4 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 27 Sep 2010 11:07:00 -0700 Subject: 3c59x: fix regression from patch "Add ethtool WOL support" This patch (commit 690a1f2002a3091bd18a501f46c9530f10481463) added a new call site for acpi_set_WOL() without checking that the function is actually suitable to be called via vortex_set_wol+0xcd/0xe0 [3c59x] dev_ethtool+0xa5a/0xb70 dev_ioctl+0x2e0/0x4b0 T.961+0x49/0x50 sock_ioctl+0x47/0x290 do_vfs_ioctl+0x7f/0x340 sys_ioctl+0x80/0xa0 system_call_fastpath+0x16/0x1b i.e. outside of code paths run when the device is not yet enabled or already disabled. In particular, putting the device into D3hot is a pretty bad idea when it was already brought up. Furthermore, all prior callers of the function made sure they're actually dealing with a PCI device, while the newly added one didn't. In the same spirit, the .get_wol handler shouldn't indicate support for WOL for non-PCI devices. Signed-off-by: Jan Beulich Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index fa42103b287..179871d9e71 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2942,6 +2942,9 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); + if (!VORTEX_PCI(vp)) + return; + wol->supported = WAKE_MAGIC; wol->wolopts = 0; @@ -2952,6 +2955,10 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); + + if (!VORTEX_PCI(vp)) + return -EOPNOTSUPP; + if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; @@ -3201,6 +3208,9 @@ static void acpi_set_WOL(struct net_device *dev) return; } + if (VORTEX_PCI(vp)->current_state < PCI_D3hot) + return; + /* Change the power state to D3; RxEnable doesn't take effect. */ pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); } -- cgit v1.2.3-70-g09d2 From 387a85628782690b56492dae4bbf544639f5d4a9 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 27 Sep 2010 11:41:45 +0000 Subject: de2104x: fix ethtool When the interface is up, using ethtool breaks it because: a) link is put down but media_timer interval is not shortened to NO_LINK b) rxtx is stopped but not restarted Also manual 10baseT-HD (and probably FD too - untested) mode does not work - the link is forced up, packets are transmitted but nothing is received. Changing CSR14 value to match documentation (not disabling link check) fixes this. Signed-off-by: Ondrej Zary Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 9124c5c638d..6888e3d4146 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -364,9 +364,9 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; -static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; +static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; /* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ -static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; +static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; @@ -1596,12 +1596,15 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) return 0; /* nothing to change */ de_link_down(de); + mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); de_stop_rxtx(de); de->media_type = new_media; de->media_lock = media_lock; de->media_advertise = ecmd->advertising; de_set_media(de); + if (netif_running(de->dev)) + de_start_rxtx(de); return 0; } -- cgit v1.2.3-70-g09d2 From e7ee762cf074b0fd8eec483d0cef8fdbf0d04b81 Mon Sep 17 00:00:00 2001 From: Florian Mickler Date: Fri, 24 Sep 2010 18:22:01 +0200 Subject: iwl3945: queue the right work if the scan needs to be aborted iwl3945's scan_completed calls into the mac80211 stack which triggers a warn on if there is no scan outstanding. This can be avoided by not calling scan_completed but abort_scan in iwl3945_request_scan in the done: branch of the function which is used as an error out. The done: branch seems to be an error-out branch, as, for example, if iwl_is_ready(priv) returns false the done: branch is executed. NOTE: I'm not familiar with the driver at all. I just quickly scanned as a reaction to https://bugzilla.kernel.org/show_bug.cgi?id=17722 the users of scan_completed in the iwl3945 driver and noted the odd discrepancy between the comment above this instance and the comment in mac80211 scan_completed function. Signed-off-by: Florian Mickler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64c2b0..8fd00a6e512 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1411,7 +1411,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } int iwlagn_manage_ibss_station(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 59a308b02f9..d31661c1ce7 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3018,7 +3018,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } static void iwl3945_bg_restart(struct work_struct *data) -- cgit v1.2.3-70-g09d2