From 169ff6db3a81fad3011e4c0b0114dbe9de1cd517 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 5 Feb 2016 15:10:02 -0800 Subject: [PATCH 001/164] ath10k: Document alloc_frag_desc_for_data_pkt config option. This will help anyone trying to use the ack-rssi reporting feature with the host-specified TX-rate option in 10.4 firmware. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index feebd19ff08c..0fae0daa9215 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2661,9 +2661,14 @@ struct wmi_resource_config_10_4 { */ __le32 iphdr_pad_config; - /* qwrap configuration + /* qwrap configuration (bits 15-0) * 1 - This is qwrap configuration * 0 - This is not qwrap + * + * Bits 31-16 is alloc_frag_desc_for_data_pkt (1 enables, 0 disables) + * In order to get ack-RSSI reporting and to specify the tx-rate for + * individual frames, this option must be enabled. This uses an extra + * 4 bytes per tx-msdu descriptor, so don't enable it unless you need it. */ __le32 qwrap_config; } __packed; From 9f0b7e7dea7c3cedba315d44816070fcc692c748 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:14 -0700 Subject: [PATCH 002/164] ath10k: add a support of set_tsf on vdev interface 10.2.4.70.24 firmware introduces new feature to set TSF via vdev parameter, hence implement relevant function. set_tsf function can be used to shift TBTT that will help avoid its clockdrift which happens when beacons are collided. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 27 +++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 4 ++++ drivers/net/wireless/ath/ath10k/wmi.h | 2 ++ 4 files changed, 34 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b0e613bc10a5..c30a3944b612 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6796,6 +6796,32 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return 0; } +static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 tsf) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + u32 tsf_offset, vdev_param = ar->wmi.vdev_param->set_tsf; + int ret; + + /* Workaround: + * + * Given tsf argument is entire TSF value, but firmware accepts + * only TSF offset to current TSF. + * + * get_tsf function is used to get offset value, however since + * ath10k_get_tsf is not implemented properly, it will return 0 always. + * Luckily all the caller functions to set_tsf, as of now, also rely on + * get_tsf function to get entire tsf value such get_tsf() + tsf_delta, + * final tsf offset value to firmware will be arithmetically correct. + */ + tsf_offset = tsf - ath10k_get_tsf(hw, vif); + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + vdev_param, tsf_offset); + if (ret && ret != -EOPNOTSUPP) + ath10k_warn(ar, "failed to set tsf offset: %d\n", ret); +} + static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) @@ -7252,6 +7278,7 @@ static const struct ieee80211_ops ath10k_ops = { .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask, .sta_rc_update = ath10k_sta_rc_update, .get_tsf = ath10k_get_tsf, + .set_tsf = ath10k_set_tsf, .ampdu_action = ath10k_ampdu_action, .get_et_sset_count = ath10k_debug_get_et_sset_count, .get_et_stats = ath10k_debug_get_et_stats, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 108593202052..e09337ee7c96 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3409,6 +3409,7 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static const struct wmi_ops wmi_tlv_ops = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index f7ec65f263a0..db3e9a4be564 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -781,6 +781,7 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; /* 10.X WMI VDEV param map */ @@ -856,6 +857,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { @@ -930,6 +932,7 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED, .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_10X_VDEV_PARAM_TSF_INCREMENT, }; static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { @@ -1005,6 +1008,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, + .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_pdev_param_map wmi_pdev_param_map = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0fae0daa9215..137edb4d451d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4635,6 +4635,7 @@ struct wmi_vdev_param_map { u32 meru_vc; u32 rx_decap_type; u32 bw_nss_ratemask; + u32 set_tsf; }; #define WMI_VDEV_PARAM_UNSUPPORTED 0 @@ -4891,6 +4892,7 @@ enum wmi_10x_vdev_param { WMI_10X_VDEV_PARAM_RTS_FIXED_RATE, WMI_10X_VDEV_PARAM_VHT_SGIMASK, WMI_10X_VDEV_PARAM_VHT80_RATEMASK, + WMI_10X_VDEV_PARAM_TSF_INCREMENT, }; enum wmi_10_4_vdev_param { From 4857dd14ec3720d25c33ea0186c55b849d891b0f Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:15 -0700 Subject: [PATCH 003/164] ath10k: update 10.4 WMI vdev parameters Update 10.4 WMI vdev param to sync to current 10.4 firmware as of 2/23/2016. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 137edb4d451d..c83e1e39f8cc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4962,6 +4962,12 @@ enum wmi_10_4_vdev_param { WMI_10_4_VDEV_PARAM_MERU_VC, WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, + WMI_10_4_VDEV_PARAM_SENSOR_AP, + WMI_10_4_VDEV_PARAM_BEACON_RATE, + WMI_10_4_VDEV_PARAM_DTIM_ENABLE_CTS, + WMI_10_4_VDEV_PARAM_STA_KICKOUT, + WMI_10_4_VDEV_PARAM_CAPABILITIES, + WMI_10_4_VDEV_PARAM_TSF_INCREMENT, }; #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) From a606c0ee9d5c12eb1a0e86837db622969956b825 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 4 Apr 2016 16:19:16 -0700 Subject: [PATCH 004/164] ath10k: enable set_tsf vdev command to WMI 10.4 10.4 firmware has addeded set_tsf vdev parameter, hence enable it. set_tsf function can be used to shift TBTT that will help avoid its clockdrift which happens when beacons are collided. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index db3e9a4be564..e8d9a3e5c2df 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1008,7 +1008,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC, .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE, .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK, - .set_tsf = WMI_VDEV_PARAM_UNSUPPORTED, + .set_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT, }; static struct wmi_pdev_param_map wmi_pdev_param_map = { From cfe9011a05a8de56f97d15a24977639fe6534e9c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:10:58 +0530 Subject: [PATCH 005/164] ath10k: remove MSI range support MSI-X is never well-tested, might contain bugs and generally isn't really all that useful to maintain. Also ath10k is mainly used with shared/singly-MSI interrupt systems. Hence removing MSI range support. This change will be useful for further cleanup in copy engine lock and to add NAPI support. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 164 +++----------------------- drivers/net/wireless/ath/ath10k/pci.h | 17 ++- 2 files changed, 24 insertions(+), 157 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0b305efe6c94..cdd8a307c55b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -33,12 +33,6 @@ #include "ce.h" #include "pci.h" -enum ath10k_pci_irq_mode { - ATH10K_PCI_IRQ_AUTO = 0, - ATH10K_PCI_IRQ_LEGACY = 1, - ATH10K_PCI_IRQ_MSI = 2, -}; - enum ath10k_pci_reset_mode { ATH10K_PCI_RESET_AUTO = 0, ATH10K_PCI_RESET_WARM_ONLY = 1, @@ -745,10 +739,7 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - if (ar_pci->num_msi_intrs > 1) - return "msi-x"; - - if (ar_pci->num_msi_intrs == 1) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_MSI) return "msi"; return "legacy"; @@ -1502,13 +1493,8 @@ void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; tasklet_kill(&ar_pci->intr_tq); - tasklet_kill(&ar_pci->msi_fw_err); - - for (i = 0; i < CE_COUNT; i++) - tasklet_kill(&ar_pci->pipe_info[i].intr); del_timer_sync(&ar_pci->rx_post_retry); } @@ -1624,10 +1610,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar) static void ath10k_pci_irq_sync(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - synchronize_irq(ar_pci->pdev->irq + i); + synchronize_irq(ar_pci->pdev->irq); } static void ath10k_pci_irq_enable(struct ath10k *ar) @@ -2596,65 +2580,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { #endif }; -static void ath10k_pci_ce_tasklet(unsigned long ptr) -{ - struct ath10k_pci_pipe *pipe = (struct ath10k_pci_pipe *)ptr; - struct ath10k_pci *ar_pci = pipe->ar_pci; - - ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num); -} - -static void ath10k_msi_err_tasklet(unsigned long data) -{ - struct ath10k *ar = (struct ath10k *)data; - - if (!ath10k_pci_has_fw_crashed(ar)) { - ath10k_warn(ar, "received unsolicited fw crash interrupt\n"); - return; - } - - ath10k_pci_irq_disable(ar); - ath10k_pci_fw_crashed_clear(ar); - ath10k_pci_fw_crashed_dump(ar); -} - -/* - * Handler for a per-engine interrupt on a PARTICULAR CE. - * This is used in cases where each CE has a private MSI interrupt. - */ -static irqreturn_t ath10k_pci_per_engine_handler(int irq, void *arg) -{ - struct ath10k *ar = arg; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL; - - if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_pci->pipe_info)) { - ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq, - ce_id); - return IRQ_HANDLED; - } - - /* - * NOTE: We are able to derive ce_id from irq because we - * use a one-to-one mapping for CE's 0..5. - * CE's 6 & 7 do not use interrupts at all. - * - * This mapping must be kept in sync with the mapping - * used by firmware. - */ - tasklet_schedule(&ar_pci->pipe_info[ce_id].intr); - return IRQ_HANDLED; -} - -static irqreturn_t ath10k_pci_msi_fw_handler(int irq, void *arg) -{ - struct ath10k *ar = arg; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - tasklet_schedule(&ar_pci->msi_fw_err); - return IRQ_HANDLED; -} - /* * Top-level interrupt handler for all PCI interrupts from a Target. * When a block of MSI interrupts is allocated, this top-level handler @@ -2672,7 +2597,7 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) return IRQ_NONE; } - if (ar_pci->num_msi_intrs == 0) { + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) { if (!ath10k_pci_irq_pending(ar)) return IRQ_NONE; @@ -2699,43 +2624,10 @@ static void ath10k_pci_tasklet(unsigned long data) ath10k_ce_per_engine_service_any(ar); /* Re-enable legacy irq that was disabled in the irq handler */ - if (ar_pci->num_msi_intrs == 0) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) ath10k_pci_enable_legacy_irq(ar); } -static int ath10k_pci_request_irq_msix(struct ath10k *ar) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int ret, i; - - ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, - ath10k_pci_msi_fw_handler, - IRQF_SHARED, "ath10k_pci", ar); - if (ret) { - ath10k_warn(ar, "failed to request MSI-X fw irq %d: %d\n", - ar_pci->pdev->irq + MSI_ASSIGN_FW, ret); - return ret; - } - - for (i = MSI_ASSIGN_CE_INITIAL; i <= MSI_ASSIGN_CE_MAX; i++) { - ret = request_irq(ar_pci->pdev->irq + i, - ath10k_pci_per_engine_handler, - IRQF_SHARED, "ath10k_pci", ar); - if (ret) { - ath10k_warn(ar, "failed to request MSI-X ce irq %d: %d\n", - ar_pci->pdev->irq + i, ret); - - for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--) - free_irq(ar_pci->pdev->irq + i, ar); - - free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar); - return ret; - } - } - - return 0; -} - static int ath10k_pci_request_irq_msi(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -2774,41 +2666,28 @@ static int ath10k_pci_request_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - switch (ar_pci->num_msi_intrs) { - case 0: + switch (ar_pci->oper_irq_mode) { + case ATH10K_PCI_IRQ_LEGACY: return ath10k_pci_request_irq_legacy(ar); - case 1: + case ATH10K_PCI_IRQ_MSI: return ath10k_pci_request_irq_msi(ar); default: - return ath10k_pci_request_irq_msix(ar); + return -EINVAL; } } static void ath10k_pci_free_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; - /* There's at least one interrupt irregardless whether its legacy INTR - * or MSI or MSI-X */ - for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) - free_irq(ar_pci->pdev->irq + i, ar); + free_irq(ar_pci->pdev->irq, ar); } void ath10k_pci_init_irq_tasklets(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar); - tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet, - (unsigned long)ar); - - for (i = 0; i < CE_COUNT; i++) { - ar_pci->pipe_info[i].ar_pci = ar_pci; - tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet, - (unsigned long)&ar_pci->pipe_info[i]); - } } static int ath10k_pci_init_irq(struct ath10k *ar) @@ -2822,20 +2701,9 @@ static int ath10k_pci_init_irq(struct ath10k *ar) ath10k_info(ar, "limiting irq mode to: %d\n", ath10k_pci_irq_mode); - /* Try MSI-X */ - if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) { - ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1; - ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, - ar_pci->num_msi_intrs); - if (ret > 0) - return 0; - - /* fall-through */ - } - /* Try MSI */ if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) { - ar_pci->num_msi_intrs = 1; + ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_MSI; ret = pci_enable_msi(ar_pci->pdev); if (ret == 0) return 0; @@ -2851,7 +2719,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar) * This write might get lost if target has NOT written BAR. * For now, fix the race by repeating the write in below * synchronization checking. */ - ar_pci->num_msi_intrs = 0; + ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY; ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL); @@ -2869,8 +2737,8 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - switch (ar_pci->num_msi_intrs) { - case 0: + switch (ar_pci->oper_irq_mode) { + case ATH10K_PCI_IRQ_LEGACY: ath10k_pci_deinit_irq_legacy(ar); break; default: @@ -2908,7 +2776,7 @@ int ath10k_pci_wait_for_target_init(struct ath10k *ar) if (val & FW_IND_INITIALIZED) break; - if (ar_pci->num_msi_intrs == 0) + if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) /* Fix potential race by repeating CORE_BASE writes */ ath10k_pci_enable_legacy_irq(ar); @@ -3186,8 +3054,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_sleep; } - ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", - ath10k_pci_get_irq_method(ar), ar_pci->num_msi_intrs, + ath10k_info(ar, "pci irq %s oper_irq_mode %d irq_mode %d reset_mode %d\n", + ath10k_pci_get_irq_method(ar), ar_pci->oper_irq_mode, ath10k_pci_irq_mode, ath10k_pci_reset_mode); ret = ath10k_pci_request_irq(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 249c73a69800..959dc321b75e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -148,9 +148,6 @@ struct ath10k_pci_pipe { /* protects compl_free and num_send_allowed */ spinlock_t pipe_lock; - - struct ath10k_pci *ar_pci; - struct tasklet_struct intr; }; struct ath10k_pci_supp_chip { @@ -164,6 +161,12 @@ struct ath10k_bus_ops { int (*get_num_banks)(struct ath10k *ar); }; +enum ath10k_pci_irq_mode { + ATH10K_PCI_IRQ_AUTO = 0, + ATH10K_PCI_IRQ_LEGACY = 1, + ATH10K_PCI_IRQ_MSI = 2, +}; + struct ath10k_pci { struct pci_dev *pdev; struct device *dev; @@ -171,14 +174,10 @@ struct ath10k_pci { void __iomem *mem; size_t mem_len; - /* - * Number of MSI interrupts granted, 0 --> using legacy PCI line - * interrupts. - */ - int num_msi_intrs; + /* Operating interrupt mode */ + enum ath10k_pci_irq_mode oper_irq_mode; struct tasklet_struct intr_tq; - struct tasklet_struct msi_fw_err; struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; From c606e662a5c8e9caa7183e7d88b7c24dadb3adea Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:16 -0400 Subject: [PATCH 006/164] rtl8xxxu: Add MAC init table for 8192eu The 8192eu requires a different MAC init table. Add the missing table and specify the table to use in the fileops structure. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 45 ++++++++++++++++--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index db8433a9efe2..2869376c0e86 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -184,6 +184,36 @@ static struct rtl8xxxu_reg8val rtl8723b_mac_init_table[] = { {0xffff, 0xff}, }; +static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { + {0x011, 0xeb}, {0x012, 0x07}, {0x014, 0x75}, {0x303, 0xa7}, + {0x428, 0x0a}, {0x429, 0x10}, {0x430, 0x00}, {0x431, 0x00}, + {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, + {0x436, 0x07}, {0x437, 0x08}, {0x43c, 0x04}, {0x43d, 0x05}, + {0x43e, 0x07}, {0x43f, 0x08}, {0x440, 0x5d}, {0x441, 0x01}, + {0x442, 0x00}, {0x444, 0x10}, {0x445, 0x00}, {0x446, 0x00}, + {0x447, 0x00}, {0x448, 0x00}, {0x449, 0xf0}, {0x44a, 0x0f}, + {0x44b, 0x3e}, {0x44c, 0x10}, {0x44d, 0x00}, {0x44e, 0x00}, + {0x44f, 0x00}, {0x450, 0x00}, {0x451, 0xf0}, {0x452, 0x0f}, + {0x453, 0x00}, {0x456, 0x5e}, {0x460, 0x66}, {0x461, 0x66}, + {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, {0x4cd, 0xff}, + {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, + {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, + {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, + {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, + {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, + {0x525, 0x4f}, {0x540, 0x12}, {0x541, 0x64}, {0x550, 0x10}, + {0x551, 0x10}, {0x559, 0x02}, {0x55c, 0x50}, {0x55d, 0xff}, + {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, {0x620, 0xff}, + {0x621, 0xff}, {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, + {0x625, 0xff}, {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, + {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, + {0x640, 0x40}, {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, + {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, {0x702, 0x65}, + {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, {0x70a, 0x65}, + {0x70b, 0x87}, + {0xffff, 0xff}, +}; + static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { {0x800, 0x80040000}, {0x804, 0x00000003}, {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, @@ -3087,8 +3117,9 @@ static void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv) } static int -rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) +rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv) { + struct rtl8xxxu_reg8val *array = priv->fops->mactable; int i, ret; u16 reg; u8 val; @@ -3103,7 +3134,8 @@ rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) ret = rtl8xxxu_write8(priv, reg, val); if (ret != 1) { dev_warn(&priv->udev->dev, - "Failed to initialize MAC\n"); + "Failed to initialize MAC " + "(reg: %04x, val %02x)\n", reg, val); return -EAGAIN; } } @@ -6369,10 +6401,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); - if (priv->rtl_chip == RTL8723B) - ret = rtl8xxxu_init_mac(priv, rtl8723b_mac_init_table); - else - ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table); + ret = rtl8xxxu_init_mac(priv); dev_dbg(dev, "%s: init_mac %i\n", __func__, ret); if (ret) @@ -8452,6 +8481,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .mactable = rtl8723a_mac_init_table, }; static struct rtl8xxxu_fileops rtl8723bu_fops = { @@ -8481,6 +8511,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, + .mactable = rtl8723b_mac_init_table, }; #ifdef CONFIG_RTL8XXXU_UNTESTED @@ -8508,6 +8539,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .mactable = rtl8723a_mac_init_table, }; #endif @@ -8536,6 +8568,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, + .mactable = rtl8192e_mac_init_table, }; static struct usb_device_id dev_table[] = { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 455e1122dbb5..94fc2172c0d0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1308,4 +1308,5 @@ struct rtl8xxxu_fileops { u32 adda_1t_path_on; u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; + struct rtl8xxxu_reg8val *mactable; }; From 2ca73dc786c4ffb9c618e7b868d69d9faf5a755d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:17 -0400 Subject: [PATCH 007/164] rtl8xxxu: Do not mess with AFE_XTAL_CTRL on 8192eu To match the vendor driver, do not mess with AFE_XTAL_CTRL on 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2869376c0e86..63fa4c66794f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3208,7 +3208,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); } - if (priv->rtl_chip != RTL8723B) { + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); val32 &= ~AFE_XTAL_RF_GATE; From 80805aa5f33e315df23b6420c64f96a28dfcbb9a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:18 -0400 Subject: [PATCH 008/164] rtl8xxxu: Set TX page boundaries for 8192eu The 8192eu also has it's own TRXFF boundary value to set. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 ++++++- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 63fa4c66794f..5b2c1c80e49d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6495,7 +6495,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Set TX buffer boundary */ - val8 = TX_TOTAL_PAGE_NUM + 1; + if (priv->rtl_chip == RTL8192E) + val8 = TX_TOTAL_PAGE_NUM_8192E + 1; + else + val8 = TX_TOTAL_PAGE_NUM + 1; if (priv->rtl_chip == RTL8723B) val8 -= 1; @@ -6532,6 +6535,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) */ if (priv->rtl_chip == RTL8723B) rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); + else if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); else rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); /* diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 94fc2172c0d0..63d72689481d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -42,6 +42,7 @@ #define REALTEK_USB_CMD_IDX 0x00 #define TX_TOTAL_PAGE_NUM 0xf8 +#define TX_TOTAL_PAGE_NUM_8192E 0xf3 /* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ #define TX_PAGE_NUM_PUBQ 0xe7 #define TX_PAGE_NUM_HI_PQ 0x0c From 19102f8419342a3cdd0efb25539a268f2d095319 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:19 -0400 Subject: [PATCH 009/164] rtl8xxxu: Add radio init tables for 8192eu Add the required radio init tables for 8192eu devices. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5b2c1c80e49d..0667aa77a2fd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1242,6 +1242,152 @@ static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { {0xff, 0xffffffff} }; +static struct rtl8xxxu_rfregval rtl8192eu_radioa_init_table[] = { + {0x7f, 0x00000082}, {0x81, 0x0003fc00}, + {0x00, 0x00030000}, {0x08, 0x00008400}, + {0x18, 0x00000407}, {0x19, 0x00000012}, + {0x1b, 0x00000064}, {0x1e, 0x00080009}, + {0x1f, 0x00000880}, {0x2f, 0x0001a060}, + {0x3f, 0x00000000}, {0x42, 0x000060c0}, + {0x57, 0x000d0000}, {0x58, 0x000be180}, + {0x67, 0x00001552}, {0x83, 0x00000000}, + {0xb0, 0x000ff9f1}, {0xb1, 0x00055418}, + {0xb2, 0x0008cc00}, {0xb4, 0x00043083}, + {0xb5, 0x00008166}, {0xb6, 0x0000803e}, + {0xb7, 0x0001c69f}, {0xb8, 0x0000407f}, + {0xb9, 0x00080001}, {0xba, 0x00040001}, + {0xbb, 0x00000400}, {0xbf, 0x000c0000}, + {0xc2, 0x00002400}, {0xc3, 0x00000009}, + {0xc4, 0x00040c91}, {0xc5, 0x00099999}, + {0xc6, 0x000000a3}, {0xc7, 0x00088820}, + {0xc8, 0x00076c06}, {0xc9, 0x00000000}, + {0xca, 0x00080000}, {0xdf, 0x00000180}, + {0xef, 0x000001a0}, {0x51, 0x00069545}, + {0x52, 0x0007e45e}, {0x53, 0x00000071}, + {0x56, 0x00051ff3}, {0x35, 0x000000a8}, + {0x35, 0x000001e2}, {0x35, 0x000002a8}, + {0x36, 0x00001c24}, {0x36, 0x00009c24}, + {0x36, 0x00011c24}, {0x36, 0x00019c24}, + {0x18, 0x00000c07}, {0x5a, 0x00048000}, + {0x19, 0x000739d0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x34, 0x0000a093}, {0x34, 0x0000908f}, + {0x34, 0x0000808c}, {0x34, 0x0000704d}, + {0x34, 0x0000604a}, {0x34, 0x00005047}, + {0x34, 0x0000400a}, {0x34, 0x00003007}, + {0x34, 0x00002004}, {0x34, 0x00001001}, + {0x34, 0x00000000}, +#else + /* Regular */ + {0x34, 0x0000add7}, {0x34, 0x00009dd4}, + {0x34, 0x00008dd1}, {0x34, 0x00007dce}, + {0x34, 0x00006dcb}, {0x34, 0x00005dc8}, + {0x34, 0x00004dc5}, {0x34, 0x000034cc}, + {0x34, 0x0000244f}, {0x34, 0x0000144c}, + {0x34, 0x00000014}, +#endif + {0x00, 0x00030159}, + {0x84, 0x00068180}, + {0x86, 0x0000014e}, + {0x87, 0x00048e00}, + {0x8e, 0x00065540}, + {0x8f, 0x00088000}, + {0xef, 0x000020a0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000f07b0}, +#else + {0x3b, 0x000f02b0}, +#endif + {0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0}, + {0x3b, 0x000cf060}, {0x3b, 0x000b0090}, + {0x3b, 0x000a0080}, {0x3b, 0x00090080}, + {0x3b, 0x0008f780}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000787b0}, +#else + {0x3b, 0x00078730}, +#endif + {0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0}, + {0x3b, 0x00040620}, {0x3b, 0x00037090}, + {0x3b, 0x00020080}, {0x3b, 0x0001f060}, + {0x3b, 0x0000ffb0}, {0xef, 0x000000a0}, + {0xfe, 0x00000000}, {0x18, 0x0000fc07}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00000001}, {0x1f, 0x00080000}, + {0x00, 0x00033e70}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192eu_radiob_init_table[] = { + {0x7f, 0x00000082}, {0x81, 0x0003fc00}, + {0x00, 0x00030000}, {0x08, 0x00008400}, + {0x18, 0x00000407}, {0x19, 0x00000012}, + {0x1b, 0x00000064}, {0x1e, 0x00080009}, + {0x1f, 0x00000880}, {0x2f, 0x0001a060}, + {0x3f, 0x00000000}, {0x42, 0x000060c0}, + {0x57, 0x000d0000}, {0x58, 0x000be180}, + {0x67, 0x00001552}, {0x7f, 0x00000082}, + {0x81, 0x0003f000}, {0x83, 0x00000000}, + {0xdf, 0x00000180}, {0xef, 0x000001a0}, + {0x51, 0x00069545}, {0x52, 0x0007e42e}, + {0x53, 0x00000071}, {0x56, 0x00051ff3}, + {0x35, 0x000000a8}, {0x35, 0x000001e0}, + {0x35, 0x000002a8}, {0x36, 0x00001ca8}, + {0x36, 0x00009c24}, {0x36, 0x00011c24}, + {0x36, 0x00019c24}, {0x18, 0x00000c07}, + {0x5a, 0x00048000}, {0x19, 0x000739d0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x34, 0x0000a093}, {0x34, 0x0000908f}, + {0x34, 0x0000808c}, {0x34, 0x0000704d}, + {0x34, 0x0000604a}, {0x34, 0x00005047}, + {0x34, 0x0000400a}, {0x34, 0x00003007}, + {0x34, 0x00002004}, {0x34, 0x00001001}, + {0x34, 0x00000000}, +#else + {0x34, 0x0000add7}, {0x34, 0x00009dd4}, + {0x34, 0x00008dd1}, {0x34, 0x00007dce}, + {0x34, 0x00006dcb}, {0x34, 0x00005dc8}, + {0x34, 0x00004dc5}, {0x34, 0x000034cc}, + {0x34, 0x0000244f}, {0x34, 0x0000144c}, + {0x34, 0x00000014}, +#endif + {0x00, 0x00030159}, {0x84, 0x00068180}, + {0x86, 0x000000ce}, {0x87, 0x00048a00}, + {0x8e, 0x00065540}, {0x8f, 0x00088000}, + {0xef, 0x000020a0}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000f07b0}, +#else + {0x3b, 0x000f02b0}, +#endif + + {0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0}, + {0x3b, 0x000cf060}, {0x3b, 0x000b0090}, + {0x3b, 0x000a0080}, {0x3b, 0x00090080}, + {0x3b, 0x0008f780}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0x3b, 0x000787b0}, +#else + {0x3b, 0x00078730}, +#endif + {0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0}, + {0x3b, 0x00040620}, {0x3b, 0x00037090}, + {0x3b, 0x00020080}, {0x3b, 0x0001f060}, + {0x3b, 0x0000ffb0}, {0xef, 0x000000a0}, + {0x00, 0x00010159}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1e, 0x00000001}, + {0x1f, 0x00080000}, {0x00, 0x00033e70}, + {0xff, 0xffffffff} +}; + static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { { /* RF_A */ .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1, @@ -6447,6 +6593,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rftable = rtl8192cu_radiob_2t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); break; + case RTL8192E: + rftable = rtl8192eu_radioa_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + break; + rftable = rtl8192eu_radiob_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + break; default: ret = -EINVAL; } From e293278debe7c1d3112aa8ec10373d73f171d75d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:20 -0400 Subject: [PATCH 010/164] rtl8xxxu: Add 8192eu AGC tables A device specific AGC table is required for the 8192eu as well. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 147 +++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0667aa77a2fd..650ebcbe7a2b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -849,6 +849,144 @@ static struct rtl8xxxu_reg32val rtl8xxx_agc_8723bu_table[] = { {0xffff, 0xffffffff} }; +static struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_std_table[] = { + {0xc78, 0xfb000001}, {0xc78, 0xfb010001}, + {0xc78, 0xfb020001}, {0xc78, 0xfb030001}, + {0xc78, 0xfb040001}, {0xc78, 0xfb050001}, + {0xc78, 0xfa060001}, {0xc78, 0xf9070001}, + {0xc78, 0xf8080001}, {0xc78, 0xf7090001}, + {0xc78, 0xf60a0001}, {0xc78, 0xf50b0001}, + {0xc78, 0xf40c0001}, {0xc78, 0xf30d0001}, + {0xc78, 0xf20e0001}, {0xc78, 0xf10f0001}, + {0xc78, 0xf0100001}, {0xc78, 0xef110001}, + {0xc78, 0xee120001}, {0xc78, 0xed130001}, + {0xc78, 0xec140001}, {0xc78, 0xeb150001}, + {0xc78, 0xea160001}, {0xc78, 0xe9170001}, + {0xc78, 0xe8180001}, {0xc78, 0xe7190001}, + {0xc78, 0xc81a0001}, {0xc78, 0xc71b0001}, + {0xc78, 0xc61c0001}, {0xc78, 0x071d0001}, + {0xc78, 0x061e0001}, {0xc78, 0x051f0001}, + {0xc78, 0x04200001}, {0xc78, 0x03210001}, + {0xc78, 0xaa220001}, {0xc78, 0xa9230001}, + {0xc78, 0xa8240001}, {0xc78, 0xa7250001}, + {0xc78, 0xa6260001}, {0xc78, 0x85270001}, + {0xc78, 0x84280001}, {0xc78, 0x83290001}, + {0xc78, 0x252a0001}, {0xc78, 0x242b0001}, + {0xc78, 0x232c0001}, {0xc78, 0x222d0001}, + {0xc78, 0x672e0001}, {0xc78, 0x662f0001}, + {0xc78, 0x65300001}, {0xc78, 0x64310001}, + {0xc78, 0x63320001}, {0xc78, 0x62330001}, + {0xc78, 0x61340001}, {0xc78, 0x45350001}, + {0xc78, 0x44360001}, {0xc78, 0x43370001}, + {0xc78, 0x42380001}, {0xc78, 0x41390001}, + {0xc78, 0x403a0001}, {0xc78, 0x403b0001}, + {0xc78, 0x403c0001}, {0xc78, 0x403d0001}, + {0xc78, 0x403e0001}, {0xc78, 0x403f0001}, + {0xc78, 0xfb400001}, {0xc78, 0xfb410001}, + {0xc78, 0xfb420001}, {0xc78, 0xfb430001}, + {0xc78, 0xfb440001}, {0xc78, 0xfb450001}, + {0xc78, 0xfa460001}, {0xc78, 0xf9470001}, + {0xc78, 0xf8480001}, {0xc78, 0xf7490001}, + {0xc78, 0xf64a0001}, {0xc78, 0xf54b0001}, + {0xc78, 0xf44c0001}, {0xc78, 0xf34d0001}, + {0xc78, 0xf24e0001}, {0xc78, 0xf14f0001}, + {0xc78, 0xf0500001}, {0xc78, 0xef510001}, + {0xc78, 0xee520001}, {0xc78, 0xed530001}, + {0xc78, 0xec540001}, {0xc78, 0xeb550001}, + {0xc78, 0xea560001}, {0xc78, 0xe9570001}, + {0xc78, 0xe8580001}, {0xc78, 0xe7590001}, + {0xc78, 0xe65a0001}, {0xc78, 0xe55b0001}, + {0xc78, 0xe45c0001}, {0xc78, 0xe35d0001}, + {0xc78, 0xe25e0001}, {0xc78, 0xe15f0001}, + {0xc78, 0x8a600001}, {0xc78, 0x89610001}, + {0xc78, 0x88620001}, {0xc78, 0x87630001}, + {0xc78, 0x86640001}, {0xc78, 0x85650001}, + {0xc78, 0x84660001}, {0xc78, 0x83670001}, + {0xc78, 0x82680001}, {0xc78, 0x6b690001}, + {0xc78, 0x6a6a0001}, {0xc78, 0x696b0001}, + {0xc78, 0x686c0001}, {0xc78, 0x676d0001}, + {0xc78, 0x666e0001}, {0xc78, 0x656f0001}, + {0xc78, 0x64700001}, {0xc78, 0x63710001}, + {0xc78, 0x62720001}, {0xc78, 0x61730001}, + {0xc78, 0x49740001}, {0xc78, 0x48750001}, + {0xc78, 0x47760001}, {0xc78, 0x46770001}, + {0xc78, 0x45780001}, {0xc78, 0x44790001}, + {0xc78, 0x437a0001}, {0xc78, 0x427b0001}, + {0xc78, 0x417c0001}, {0xc78, 0x407d0001}, + {0xc78, 0x407e0001}, {0xc78, 0x407f0001}, + {0xc50, 0x00040022}, {0xc50, 0x00040020}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_highpa_table[] = { + {0xc78, 0xfa000001}, {0xc78, 0xf9010001}, + {0xc78, 0xf8020001}, {0xc78, 0xf7030001}, + {0xc78, 0xf6040001}, {0xc78, 0xf5050001}, + {0xc78, 0xf4060001}, {0xc78, 0xf3070001}, + {0xc78, 0xf2080001}, {0xc78, 0xf1090001}, + {0xc78, 0xf00a0001}, {0xc78, 0xef0b0001}, + {0xc78, 0xee0c0001}, {0xc78, 0xed0d0001}, + {0xc78, 0xec0e0001}, {0xc78, 0xeb0f0001}, + {0xc78, 0xea100001}, {0xc78, 0xe9110001}, + {0xc78, 0xe8120001}, {0xc78, 0xe7130001}, + {0xc78, 0xe6140001}, {0xc78, 0xe5150001}, + {0xc78, 0xe4160001}, {0xc78, 0xe3170001}, + {0xc78, 0xe2180001}, {0xc78, 0xe1190001}, + {0xc78, 0x8a1a0001}, {0xc78, 0x891b0001}, + {0xc78, 0x881c0001}, {0xc78, 0x871d0001}, + {0xc78, 0x861e0001}, {0xc78, 0x851f0001}, + {0xc78, 0x84200001}, {0xc78, 0x83210001}, + {0xc78, 0x82220001}, {0xc78, 0x6a230001}, + {0xc78, 0x69240001}, {0xc78, 0x68250001}, + {0xc78, 0x67260001}, {0xc78, 0x66270001}, + {0xc78, 0x65280001}, {0xc78, 0x64290001}, + {0xc78, 0x632a0001}, {0xc78, 0x622b0001}, + {0xc78, 0x612c0001}, {0xc78, 0x602d0001}, + {0xc78, 0x472e0001}, {0xc78, 0x462f0001}, + {0xc78, 0x45300001}, {0xc78, 0x44310001}, + {0xc78, 0x43320001}, {0xc78, 0x42330001}, + {0xc78, 0x41340001}, {0xc78, 0x40350001}, + {0xc78, 0x40360001}, {0xc78, 0x40370001}, + {0xc78, 0x40380001}, {0xc78, 0x40390001}, + {0xc78, 0x403a0001}, {0xc78, 0x403b0001}, + {0xc78, 0x403c0001}, {0xc78, 0x403d0001}, + {0xc78, 0x403e0001}, {0xc78, 0x403f0001}, + {0xc78, 0xfa400001}, {0xc78, 0xf9410001}, + {0xc78, 0xf8420001}, {0xc78, 0xf7430001}, + {0xc78, 0xf6440001}, {0xc78, 0xf5450001}, + {0xc78, 0xf4460001}, {0xc78, 0xf3470001}, + {0xc78, 0xf2480001}, {0xc78, 0xf1490001}, + {0xc78, 0xf04a0001}, {0xc78, 0xef4b0001}, + {0xc78, 0xee4c0001}, {0xc78, 0xed4d0001}, + {0xc78, 0xec4e0001}, {0xc78, 0xeb4f0001}, + {0xc78, 0xea500001}, {0xc78, 0xe9510001}, + {0xc78, 0xe8520001}, {0xc78, 0xe7530001}, + {0xc78, 0xe6540001}, {0xc78, 0xe5550001}, + {0xc78, 0xe4560001}, {0xc78, 0xe3570001}, + {0xc78, 0xe2580001}, {0xc78, 0xe1590001}, + {0xc78, 0x8a5a0001}, {0xc78, 0x895b0001}, + {0xc78, 0x885c0001}, {0xc78, 0x875d0001}, + {0xc78, 0x865e0001}, {0xc78, 0x855f0001}, + {0xc78, 0x84600001}, {0xc78, 0x83610001}, + {0xc78, 0x82620001}, {0xc78, 0x6a630001}, + {0xc78, 0x69640001}, {0xc78, 0x68650001}, + {0xc78, 0x67660001}, {0xc78, 0x66670001}, + {0xc78, 0x65680001}, {0xc78, 0x64690001}, + {0xc78, 0x636a0001}, {0xc78, 0x626b0001}, + {0xc78, 0x616c0001}, {0xc78, 0x606d0001}, + {0xc78, 0x476e0001}, {0xc78, 0x466f0001}, + {0xc78, 0x45700001}, {0xc78, 0x44710001}, + {0xc78, 0x43720001}, {0xc78, 0x42730001}, + {0xc78, 0x41740001}, {0xc78, 0x40750001}, + {0xc78, 0x40760001}, {0xc78, 0x40770001}, + {0xc78, 0x40780001}, {0xc78, 0x40790001}, + {0xc78, 0x407a0001}, {0xc78, 0x407b0001}, + {0xc78, 0x407c0001}, {0xc78, 0x407d0001}, + {0xc78, 0x407e0001}, {0xc78, 0x407f0001}, + {0xc50, 0x00040222}, {0xc50, 0x00040220}, + {0xffff, 0xffffffff} +}; + static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = { {0x00, 0x00030159}, {0x01, 0x00031284}, {0x02, 0x00098000}, {0x03, 0x00039c63}, @@ -3446,7 +3584,14 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8723B) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->hi_pa) + else if (priv->rtl_chip == RTL8192E) { + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_std_table); + } else if (priv->hi_pa) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); else rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); From ae14c5d20dc9e5e66681a7e3045b61eb9348d9f4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:21 -0400 Subject: [PATCH 011/164] rtl8xxxu: Add 8192eu PHY init table The 8192eu also requires it's own PHY init table. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 650ebcbe7a2b..48d2d56ec224 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -610,6 +610,138 @@ static struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = { {0xffff, 0xffffffff}, }; +static struct rtl8xxxu_reg32val rtl8192eu_phy_init_table[] = { + {0x800, 0x80040000}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10001331}, {0x814, 0x020c3d10}, + {0x818, 0x02220385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390204}, + {0x828, 0x01000100}, {0x82c, 0x00390204}, + {0x830, 0x32323232}, {0x834, 0x30303030}, + {0x838, 0x30303030}, {0x83c, 0x30303030}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x28282828}, {0x84c, 0x28282828}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x009a009a}, {0x85c, 0x01000014}, + {0x860, 0x66f60000}, {0x864, 0x061f0000}, + {0x868, 0x30303030}, {0x86c, 0x30303030}, + {0x870, 0x00000000}, {0x874, 0x55004200}, + {0x878, 0x08080808}, {0x87c, 0x00000000}, + {0x880, 0xb0000c1c}, {0x884, 0x00000001}, + {0x888, 0x00000000}, {0x88c, 0xcc0000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x900, 0x00000000}, + {0x904, 0x00000023}, {0x908, 0x00000000}, + {0x90c, 0x81121313}, {0x910, 0x806c0001}, + {0x914, 0x00000001}, {0x918, 0x00000000}, + {0x91c, 0x00010000}, {0x924, 0x00000001}, + {0x928, 0x00000000}, {0x92c, 0x00000000}, + {0x930, 0x00000000}, {0x934, 0x00000000}, + {0x938, 0x00000000}, {0x93c, 0x00000000}, + {0x940, 0x00000000}, {0x944, 0x00000000}, + {0x94c, 0x00000008}, {0xa00, 0x00d0c7c8}, + {0xa04, 0x81ff000c}, {0xa08, 0x8c838300}, + {0xa0c, 0x2e68120f}, {0xa10, 0x95009b78}, + {0xa14, 0x1114d028}, {0xa18, 0x00881117}, + {0xa1c, 0x89140f00}, {0xa20, 0x1a1b0000}, + {0xa24, 0x090e1317}, {0xa28, 0x00000204}, + {0xa2c, 0x00d30000}, {0xa70, 0x101fff00}, + {0xa74, 0x00000007}, {0xa78, 0x00000900}, + {0xa7c, 0x225b0606}, {0xa80, 0x218075b1}, + {0xb38, 0x00000000}, {0xc00, 0x48071d40}, + {0xc04, 0x03a05633}, {0xc08, 0x000000e4}, + {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000}, + {0xc14, 0x40000100}, {0xc18, 0x08800000}, + {0xc1c, 0x40000100}, {0xc20, 0x00000000}, + {0xc24, 0x00000000}, {0xc28, 0x00000000}, + {0xc2c, 0x00000000}, {0xc30, 0x69e9ac47}, + {0xc34, 0x469652af}, {0xc38, 0x49795994}, + {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f}, + {0xc44, 0x000100b7}, {0xc48, 0xec020107}, + {0xc4c, 0x007f037f}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc50, 0x00340220}, +#else + {0xc50, 0x00340020}, +#endif + {0xc54, 0x0080801f}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc58, 0x00000220}, +#else + {0xc58, 0x00000020}, +#endif + {0xc5c, 0x00248492}, {0xc60, 0x00000000}, + {0xc64, 0x7112848b}, {0xc68, 0x47c00bff}, + {0xc6c, 0x00000036}, {0xc70, 0x00000600}, + {0xc74, 0x02013169}, {0xc78, 0x0000001f}, + {0xc7c, 0x00b91612}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc80, 0x2d4000b5}, +#else + {0xc80, 0x40000100}, +#endif + {0xc84, 0x21f60000}, +#ifdef EXT_PA_8192EU + /* External PA or external LNA */ + {0xc88, 0x2d4000b5}, +#else + {0xc88, 0x40000100}, +#endif + {0xc8c, 0xa0e40000}, {0xc90, 0x00121820}, + {0xc94, 0x00000000}, {0xc98, 0x00121820}, + {0xc9c, 0x00007f7f}, {0xca0, 0x00000000}, + {0xca4, 0x000300a0}, {0xca8, 0x00000000}, + {0xcac, 0x00000000}, {0xcb0, 0x00000000}, + {0xcb4, 0x00000000}, {0xcb8, 0x00000000}, + {0xcbc, 0x28000000}, {0xcc0, 0x00000000}, + {0xcc4, 0x00000000}, {0xcc8, 0x00000000}, + {0xccc, 0x00000000}, {0xcd0, 0x00000000}, + {0xcd4, 0x00000000}, {0xcd8, 0x64b22427}, + {0xcdc, 0x00766932}, {0xce0, 0x00222222}, + {0xce4, 0x00040000}, {0xce8, 0x77644302}, + {0xcec, 0x2f97d40c}, {0xd00, 0x00080740}, + {0xd04, 0x00020403}, {0xd08, 0x0000907f}, + {0xd0c, 0x20010201}, {0xd10, 0xa0633333}, + {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b}, + {0xd1c, 0x0000007f}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00127353}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000282}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xd80, 0x01081008}, + {0xd84, 0x00000800}, {0xd88, 0xf0b50000}, + {0xe00, 0x30303030}, {0xe04, 0x30303030}, + {0xe08, 0x03903030}, {0xe10, 0x30303030}, + {0xe14, 0x30303030}, {0xe18, 0x30303030}, + {0xe1c, 0x30303030}, {0xe28, 0x00000000}, + {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f}, + {0xe38, 0x02140102}, {0xe3c, 0x681604c2}, + {0xe40, 0x01007c00}, {0xe44, 0x01004800}, + {0xe48, 0xfb000000}, {0xe4c, 0x000028d1}, + {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f}, + {0xe58, 0x02140102}, {0xe5c, 0x28160d05}, + {0xe60, 0x00000008}, {0xe68, 0x0fc05656}, + {0xe6c, 0x03c09696}, {0xe70, 0x03c09696}, + {0xe74, 0x0c005656}, {0xe78, 0x0c005656}, + {0xe7c, 0x0c005656}, {0xe80, 0x0c005656}, + {0xe84, 0x03c09696}, {0xe88, 0x0c005656}, + {0xe8c, 0x03c09696}, {0xed0, 0x03c09696}, + {0xed4, 0x03c09696}, {0xed8, 0x03c09696}, + {0xedc, 0x0000d6d6}, {0xee0, 0x0000d6d6}, + {0xeec, 0x0fc01616}, {0xee4, 0xb0000c1c}, + {0xee8, 0x00000001}, {0xf14, 0x00000003}, + {0xf4c, 0x00000000}, {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + static struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = { {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, @@ -3516,6 +3648,14 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); + } else if (priv->rtl_chip == RTL8192E) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | + SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); } else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); From abd71bdb94c3c4cd6bf4837ce568cb189fdb7f7a Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:22 -0400 Subject: [PATCH 012/164] rtl8xxxu: Pick PHY init table based on chip version first Pick PHY init table based on device before distinguishing between 1T/2T/high PA tables. The latter is only currently used for 8188cu/8192cu/8188ru. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 48d2d56ec224..fcbb67936112 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3637,11 +3637,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); - else if (priv->tx_paths == 2) - rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); - else if (priv->rtl_chip == RTL8723B) { + if (priv->rtl_chip == RTL8723B) { /* * Why? */ @@ -3656,10 +3652,13 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); - } else + } else if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); + else if (priv->tx_paths == 2) + rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); + else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); - if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); From 9e24772ae222a867f98efc5502a5a01b3916db83 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:23 -0400 Subject: [PATCH 013/164] rtl8xxxu: Correctly parse 8192eu efuse The 8192eu efuse only has power data for path A and B. It follows the same layout as 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 40 +++++++++++++++++++ .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 40 ++++++++----------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index fcbb67936112..539f7b58bbf7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2122,6 +2122,9 @@ static int rtl8723a_channel_to_group(int channel) return group; } +/* + * Valid for rtl8723bu and rtl8192eu + */ static int rtl8723b_channel_to_group(int channel) { int group; @@ -2987,6 +2990,43 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) ether_addr_copy(priv->mac_addr, efuse->mac_addr); + memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base, + sizeof(efuse->tx_power_index_A.cck_base)); + memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base, + sizeof(efuse->tx_power_index_B.cck_base)); + + memcpy(priv->ht40_1s_tx_power_index_A, + efuse->tx_power_index_A.ht40_base, + sizeof(efuse->tx_power_index_A.ht40_base)); + memcpy(priv->ht40_1s_tx_power_index_B, + efuse->tx_power_index_B.ht40_base, + sizeof(efuse->tx_power_index_B.ht40_base)); + + priv->ht20_tx_power_diff[0].a = + efuse->tx_power_index_A.ht20_ofdm_1s_diff.b; + priv->ht20_tx_power_diff[0].b = + efuse->tx_power_index_B.ht20_ofdm_1s_diff.b; + + priv->ht40_tx_power_diff[0].a = 0; + priv->ht40_tx_power_diff[0].b = 0; + + for (i = 1; i < RTL8723B_TX_COUNT; i++) { + priv->ofdm_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ofdm; + priv->ofdm_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ofdm; + + priv->ht20_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht20; + priv->ht20_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht20; + + priv->ht40_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht40; + priv->ht40_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht40; + } + priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 63d72689481d..48a80fa9eac2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -788,55 +788,49 @@ struct rtl8192eu_efuse_tx_power { u8 cck_base[6]; u8 ht40_base[5]; struct rtl8723au_idx ht20_ofdm_1s_diff; - struct rtl8723au_idx ht40_ht20_2s_diff; - struct rtl8723au_idx ofdm_cck_2s_diff; /* not used */ - struct rtl8723au_idx ht40_ht20_3s_diff; - struct rtl8723au_idx ofdm_cck_3s_diff; /* not used */ - struct rtl8723au_idx ht40_ht20_4s_diff; - struct rtl8723au_idx ofdm_cck_4s_diff; /* not used */ + struct rtl8723bu_pwr_idx pwr_diff[3]; + u8 dummy5g[24]; /* max channel group (14) + power diff offset (10) */ }; struct rtl8192eu_efuse { __le16 rtl_id; u8 res0[0x0e]; struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */ - struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x22 */ - struct rtl8192eu_efuse_tx_power tx_power_index_C; /* 0x34 */ - struct rtl8192eu_efuse_tx_power tx_power_index_D; /* 0x46 */ - u8 res1[0x60]; + struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */ + u8 res2[0x54]; u8 channel_plan; /* 0xb8 */ u8 xtal_k; u8 thermal_meter; u8 iqk_lck; u8 pa_type; /* 0xbc */ u8 lna_type_2g; /* 0xbd */ - u8 res2[1]; + u8 res3[1]; u8 lna_type_5g; /* 0xbf */ - u8 res13[1]; + u8 res4[1]; u8 rf_board_option; u8 rf_feature_option; u8 rf_bt_setting; u8 eeprom_version; u8 eeprom_customer_id; - u8 res3[3]; + u8 res5[3]; u8 rf_antenna_option; /* 0xc9 */ - u8 res4[6]; + u8 res6[6]; u8 vid; /* 0xd0 */ - u8 res5[1]; + u8 res7[1]; u8 pid; /* 0xd2 */ - u8 res6[1]; + u8 res8[1]; u8 usb_optional_function; - u8 res7[2]; - u8 mac_addr[ETH_ALEN]; /* 0xd7 */ - u8 res8[2]; - u8 vendor_name[7]; u8 res9[2]; - u8 device_name[0x0b]; /* 0xe8 */ + u8 mac_addr[ETH_ALEN]; /* 0xd7 */ u8 res10[2]; + u8 vendor_name[7]; + u8 res11[2]; + u8 device_name[0x0b]; /* 0xe8 */ + u8 res12[2]; u8 serial[0x0b]; /* 0xf5 */ - u8 res11[0x30]; + u8 res13[0x30]; u8 unknown[0x0d]; /* 0x130 */ - u8 res12[0xc3]; + u8 res14[0xc3]; }; struct rtl8xxxu_reg8val { From 444004bd134990456329267ac6365e71d73aeb85 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:24 -0400 Subject: [PATCH 014/164] rtl8xxxu: Handle BB init for 8192eu The 8192eu does not use REG_AFE_PLL_CTRL in it's BB init sequence, so provide device specific handling. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 539f7b58bbf7..dc67f5b2dbae 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3649,6 +3649,11 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); + } else if (priv->rtl_chip == RTL8192E) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | + SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); } else { val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); udelay(2); From 2949b9ee77b819b90d23096ef44744244283e630 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:25 -0400 Subject: [PATCH 015/164] rtl8xxxu: Provide special handling when writing RF regs on 8192eu The 8192eu requires clearing/restoring bit 17 in REG_FPGA0_POWER_SAVE before/after writing RF registers. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index dc67f5b2dbae..ad5b3d3f7084 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1896,7 +1896,7 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, enum rtl8xxxu_rfpath path, u8 reg, u32 data) { int ret, retval; - u32 dataaddr; + u32 dataaddr, val32; if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE) dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", @@ -1905,6 +1905,12 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, data &= FPGA0_LSSI_PARM_DATA_MASK; dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data; + if (priv->rtl_chip == RTL8192E) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 &= ~0x20000; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + } + /* Use XB for path B */ ret = rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].lssiparm, dataaddr); if (ret != sizeof(dataaddr)) @@ -1914,6 +1920,12 @@ static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, udelay(1); + if (priv->rtl_chip == RTL8192E) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 |= 0x20000; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + } + return retval; } From 8a59485c8ee911e77ace1622520976321aaf3820 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:26 -0400 Subject: [PATCH 016/164] rtl8xxxu: Handle XTAL value setting on 8192eu Set REG_AFE_XTAL_CTRL on 8192eu to the vendor driver value, and do not skip setting REG_MAX_AGGR_NUM on 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ad5b3d3f7084..e77019256c61 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3608,7 +3608,7 @@ rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv) } } - if (priv->rtl_chip != RTL8723B) + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a); return 0; @@ -3813,6 +3813,9 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); } + if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x000f81fb); + return 0; } From 57e5e2e650fb7ad1fe32e1c5e5b1bd01faa238fc Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:27 -0400 Subject: [PATCH 017/164] rtl8xxxu: Set correct interrupt masking registers on 8192eu Set HIMR[01] on 8192eu instead of HISR/HIMR. It's not obvious this really matters for USB devices, but this matches the register writes performed by the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e77019256c61..bcf229d2055b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6883,11 +6883,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, 0xfe42, 0x80); } - if (priv->rtl_chip == RTL8192E) { - rtl8xxxu_write32(priv, REG_HIMR0, 0x00); - rtl8xxxu_write32(priv, REG_HIMR1, 0x00); - } - if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); @@ -7053,11 +7048,16 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) */ rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4); - /* - * Enable all interrupts - not obvious USB needs to do this - */ - rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); - rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + if (priv->rtl_chip == RTL8192E) { + rtl8xxxu_write32(priv, REG_HIMR0, 0x00); + rtl8xxxu_write32(priv, REG_HIMR1, 0x00); + } else { + /* + * Enable all interrupts - not obvious USB needs to do this + */ + rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); + rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + } rtl8xxxu_set_mac(priv); rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION); From 3021e51f2b2f62a2fa6f49c2d14d103b5a8c331c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:28 -0400 Subject: [PATCH 018/164] rtl8xxxu: Set REG_USB_HRPWM for 8192eu The vendor driver set register 0xfe58 REG_USB_HWPWM in it's init sequence for 8192eu. Do the same here. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 ++ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bcf229d2055b..fdd11ece3806 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7225,6 +7225,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val32 |= FPGA_RF_MODE_CCK; rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); } + } else if (priv->rtl_chip == RTL8192E) { + rtl8xxxu_write8(priv, REG_USB_HRPWM, 0x00); } val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index ade42fe7e742..82cbe856694a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1043,6 +1043,7 @@ #define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ #define REG_USB_SPECIAL_OPTION 0xfe55 +#define REG_USB_HRPWM 0xfe58 #define REG_USB_DMA_AGG_TO 0xfe5b #define REG_USB_AGG_TO 0xfe5c #define REG_USB_AGG_TH 0xfe5d From e1394fe5f98638ac0231063245614bb20e94e57f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:29 -0400 Subject: [PATCH 019/164] rtl8xxxu: Fix LDPC RX hang issue on 8192eu Implement workaround for LDPC RX hands on 8192eu. This was inspired by workaround found in the 8192eu vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index fdd11ece3806..ed266f081fd0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7234,6 +7234,16 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* ack for xmit mgmt frames. */ rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val32); + if (priv->rtl_chip == RTL8192E) { + /* + * Fix LDPC rx hang issue. + */ + val32 = rtl8xxxu_read32(priv, REG_AFE_MISC); + rtl8xxxu_write8(priv, REG_8192E_LDOV12_CTRL, 0x75); + val32 &= 0xfff00fff; + val32 |= 0x0007e000; + rtl8xxxu_write32(priv, REG_8192E_LDOV12_CTRL, val32); + } exit: return ret; } From b052b7fc7d25f7c783ffcd87c42b767f6c166724 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:30 -0400 Subject: [PATCH 020/164] rtl8xxxu: Implement 8192eu device specific quirks Set REG_QUEUE_CTRL and REG_ACLK_MON for 8192eu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 ++++++++++++++ .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ed266f081fd0..3e96ba25bf91 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7197,6 +7197,20 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->fops->init_statistics) priv->fops->init_statistics(priv); + if (priv->rtl_chip == RTL8192E) { + /* + * 0x4c6[3] 1: RTS BW = Data BW + * 0: RTS BW depends on CCA / secondary CCA result. + */ + val8 = rtl8xxxu_read8(priv, REG_QUEUE_CTRL); + val8 &= ~BIT(3); + rtl8xxxu_write8(priv, REG_QUEUE_CTRL, val8); + /* + * Reset USB mode switch setting + */ + rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00); + } + rtl8723a_phy_lc_calibrate(priv); priv->fops->phy_iq_calibrate(priv); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 82cbe856694a..c19f234f1934 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -512,6 +512,7 @@ #define REG_PKT_VO_VI_LIFE_TIME 0x04c0 #define REG_PKT_BE_BK_LIFE_TIME 0x04c2 #define REG_STBC_SETTING 0x04c4 +#define REG_QUEUE_CTRL 0x04c6 #define REG_HT_SINGLE_AMPDU_8723B 0x04c7 #define REG_PROT_MODE_CTRL 0x04c8 #define REG_MAX_AGGR_NUM 0x04ca From 70bc1e24d9e2df3002d714348ca600db83de4c64 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:31 -0400 Subject: [PATCH 021/164] rtl8xxxu: Use proper register name for REG_PAD_CTRL1 Fixup another case where the hard coded register value was used instead of the name. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3e96ba25bf91..cd536c0a2387 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3550,9 +3550,9 @@ static void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv) { u32 val32; - val32 = rtl8xxxu_read32(priv, 0x64); + val32 = rtl8xxxu_read32(priv, REG_PAD_CTRL1); val32 &= ~(BIT(20) | BIT(24)); - rtl8xxxu_write32(priv, 0x64, val32); + rtl8xxxu_write32(priv, REG_PAD_CTRL1, val32); val32 = rtl8xxxu_read32(priv, REG_GPIO_MUXCFG); val32 &= ~BIT(4); From f991f4e9147b1b7c9546c08f80d8d8f0aa53df2e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:32 -0400 Subject: [PATCH 022/164] rtl8xxxu: Implement IQK calibration for 8192eu 8192eu has it's own IQK calibration procedure, and notably uses undocumented RF register 0x56 in the process. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 608 +++++++++++++++++- .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 1 + 2 files changed, 608 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index cd536c0a2387..c08bbcbe4a0d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4955,6 +4955,334 @@ static int rtl8723bu_iqk_path_b(struct rtl8xxxu_priv *priv) } #endif +static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c; + int result = 0; + + /* + * TX IQK + * PA/PAD controlled by 0x0 + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140303); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + + return result; +} + +static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32; + int result = 0; + + /* Leave IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00); + + /* Enable path A PA in TX IQK mode */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf117b); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* TX IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + goto out; + } + + val32 = 0x80007c00 | + (reg_e94 & 0x03ff0000) | ((reg_e9c >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ffa); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n", + __func__); + +out: + return result; +} + +static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc; + int result = 0; + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x821403e2); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00492911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n", + __func__); + + return result; +} + +static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32; + int result = 0; + + /* Leave IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + /* Enable path A PA in TX IQK mode */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf117b); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* TX IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* + * PA/PAD controlled by 0x0 + * Vendor driver restores RF_A here which I believe is a bug + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + goto out; + } + + val32 = 0x80007c00 | + (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ffa); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000); + + /* Enter IQK mode */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* Path A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(10); + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + + if (!(reg_eac & BIT(30)) && + ((reg_ec4 & 0x03ff0000) != 0x01320000) && + ((reg_ecc & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); + +out: + return result; +} + static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, int result[][8], int t) { @@ -5385,6 +5713,194 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, } } +static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + struct device *dev = &priv->udev->dev; + u32 i, val32; + int path_a_ok, path_b_ok; + int retry = 2; + const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { + REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, + REG_FPGA0_XB_RF_INT_OE, REG_CCK0_AFE_SETTING + }; + u8 xa_agc = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1) & 0xff; + u8 xb_agc = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1) & 0xff; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + rtl8xxxu_path_adda_on(priv, adda_regs, true); + + /* MAC settings */ + rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup); + + val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 |= 0x0f000000; + rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); + + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22208200); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); + val32 |= BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32); + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE); + val32 |= BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192eu_iqk_path_a(priv); + if (path_a_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + + break; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A TX IQK failed!\n", __func__); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192eu_rx_iqk_path_a(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + + break; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__); + + if (priv->rf_paths > 1) { + dev_warn(dev, "%s: Path B ongoing\n", __func__); + + /* Path A into standby */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x10000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Turn Path B ADDA on */ + rtl8xxxu_path_adda_on(priv, adda_regs, false); + + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192eu_iqk_path_b(priv); + if (path_b_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + break; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B IQK failed!\n", __func__); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192eu_rx_iqk_path_b(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B RX IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); + + if (t) { + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + + /* Restore RX initial gain */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + val32 &= 0xffffff00; + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | 0x50); + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | xa_agc); + + if (priv->rf_paths > 1) { + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1); + val32 &= 0xffffff00; + rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1, + val32 | 0x50); + rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1, + val32 | xb_agc); + } + + /* Load 0xe30 IQC default value */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00); + } +} + static void rtl8xxxu_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start) { struct h2c_cmd h2c; @@ -5630,6 +6146,96 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_prepare_calibrate(priv, 0); } +static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int result[4][8]; /* last is final result */ + int i, candidate; + bool path_a_ok, path_b_ok; + u32 reg_e94, reg_e9c, reg_ea4, reg_eac; + u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + bool simu; + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + for (i = 0; i < 3; i++) { + rtl8192eu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + if (simu) + candidate = 1; + else + candidate = 3; + } + } + + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + priv->rege94 = reg_e94; + reg_e9c = result[candidate][1]; + priv->rege9c = reg_e9c; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + priv->regeb4 = reg_eb4; + reg_ebc = result[candidate][5]; + priv->regebc = reg_ebc; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, + "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x " + "ecc=%x\n ", __func__, reg_e94, reg_e9c, + reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc); + path_a_ok = true; + path_b_ok = true; + } else { + reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100; + reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0; + } + + if (reg_e94 && candidate >= 0) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (priv->rf_paths > 1) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + + rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, RTL8XXXU_BB_REGS); +} + static void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv) { u32 val32; @@ -9080,7 +9686,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, - .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, + .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8723bu_parse_rx_desc, .enable_rf = rtl8723b_enable_rf, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index c19f234f1934..2aa14b14a0a5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1130,6 +1130,7 @@ #define RF6052_REG_T_METER_8723B 0x42 #define RF6052_REG_UNKNOWN_43 0x43 #define RF6052_REG_UNKNOWN_55 0x55 +#define RF6052_REG_UNKNOWN_56 0x56 #define RF6052_REG_S0S1 0xb0 #define RF6052_REG_UNKNOWN_DF 0xdf #define RF6052_REG_UNKNOWN_ED 0xed From 28e460b02c66116354ced05b570503d252b996e9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 7 Apr 2016 14:19:33 -0400 Subject: [PATCH 023/164] rtl8xxxu: Adjust AFE crystal value on 8192eu Adjust AFE before enabling PLL on 8192eu, probably also needed for 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 39 +++++++++++++++++++ .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 4 ++ 2 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c08bbcbe4a0d..e36fda8c1ad3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7093,6 +7093,41 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) #endif +/* + * This is needed for 8723bu as well, presumable + */ +static void rtl8192e_crystal_afe_adjust(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + /* + * 40Mhz crystal source, MAC 0x28[2]=0 + */ + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + val8 &= 0xfb; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + + val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4); + val32 &= 0xfffffc7f; + rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32); + + /* + * 92e AFE parameter + * AFE PLL KVCO selection, MAC 0x28[6]=1 + */ + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + val8 &= 0xbf; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + + /* + * AFE PLL KVCO selection, MAC 0x78[21]=0 + */ + val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4); + val32 &= 0xffdfffff; + rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32); +} + static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv) { u16 val16; @@ -7115,6 +7150,10 @@ static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_LDO_SW_CTRL, 0x83); } + /* + * Adjust AFE before enabling PLL + */ + rtl8192e_crystal_afe_adjust(priv); rtl8192e_disabled_to_emu(priv); ret = rtl8192e_emu_to_active(priv); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 2aa14b14a0a5..bb08a3939e46 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -109,6 +109,9 @@ #define AFE_XTAL_GATE_DIG BIT(17) #define AFE_XTAL_BT_GATE BIT(20) +/* + * 0x0028 is also known as REG_AFE_CTRL2 on 8723bu/8192eu + */ #define REG_AFE_PLL_CTRL 0x0028 #define AFE_PLL_ENABLE BIT(0) #define AFE_PLL_320_ENABLE BIT(1) @@ -192,6 +195,7 @@ control */ #define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */ +#define REG_AFE_CTRL4 0x0078 /* 8192eu/8723bu */ #define REG_LDO_SW_CTRL 0x007c /* 8192eu */ #define REG_MCU_FW_DL 0x0080 From 7fde010d473d7eb98a2af3dd91e83838a1f24cdf Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:21 +0200 Subject: [PATCH 024/164] brcmfmac: clear eventmask array before using it When the event_msgs iovar is set an array is used to configure the enabled events. This arrays needs to nulled before configuring otherwise unhandled events will be enabled. This solves a problem where in case of wowl the host got woken by an incorrectly enabled event. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index d414fbbcc814..b390561255b3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -371,6 +371,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) int i, err; s8 eventmask[BRCMF_EVENTING_MASK_LEN]; + memset(eventmask, 0, sizeof(eventmask)); for (i = 0; i < BRCMF_E_LAST; i++) { if (ifp->drvr->fweh.evt_handler[i]) { brcmf_dbg(EVENT, "enable event %s\n", From 28b285a6129d0c19bcf9e40bb7767da0fd62974f Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:22 +0200 Subject: [PATCH 025/164] brcmfmac: fix clearing wowl wake indicators Newer firmwares require the usage of the wowl wakeind struct as size for the iovar to clear the wake indicators. Older firmwares do not care, so change the used size. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 9a567e263bb1..8daad782b3c3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3608,7 +3608,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) wowl_config |= BRCMF_WOWL_UNASSOC; - brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear")); + brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", + sizeof(struct brcmf_wowl_wakeind_le)); brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); brcmf_bus_wowl_config(cfg->pub->bus_if, true); From 46f2b38a91b08ec7faf1839c3cdcec3cfcc6ad50 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:23 +0200 Subject: [PATCH 026/164] brcmfmac: insert default boardrev in nvram data if missing Some nvram files/stores come without the boardrev information, but firmware requires this to be set. When not found in nvram then add a default boardrev string to the nvram data. Reported-by: Rafal Milecki Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/firmware.c | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 7269056d0044..c7c1e9906500 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -29,6 +29,7 @@ #define BRCMF_FW_MAX_NVRAM_SIZE 64000 #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ +#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff" enum nvram_parser_state { IDLE, @@ -51,6 +52,7 @@ enum nvram_parser_state { * @entry: start position of key,value entry. * @multi_dev_v1: detect pcie multi device v1 (compressed). * @multi_dev_v2: detect pcie multi device v2. + * @boardrev_found: nvram contains boardrev information. */ struct nvram_parser { enum nvram_parser_state state; @@ -63,6 +65,7 @@ struct nvram_parser { u32 entry; bool multi_dev_v1; bool multi_dev_v2; + bool boardrev_found; }; /** @@ -125,6 +128,8 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) nvp->multi_dev_v1 = true; if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0) nvp->multi_dev_v2 = true; + if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0) + nvp->boardrev_found = true; } else if (!is_nvram_char(c) || c == ' ') { brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", nvp->line, nvp->column); @@ -284,6 +289,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, while (i < nvp->nvram_len) { if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) { i += 2; + if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0) + nvp->boardrev_found = true; while (nvp->nvram[i] != 0) { nvram[j] = nvp->nvram[i]; i++; @@ -335,6 +342,8 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, while (i < nvp->nvram_len - len) { if (strncmp(&nvp->nvram[i], prefix, len) == 0) { i += len; + if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0) + nvp->boardrev_found = true; while (nvp->nvram[i] != 0) { nvram[j] = nvp->nvram[i]; i++; @@ -356,6 +365,18 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, nvp->nvram_len = 0; } +static void brcmf_fw_add_defaults(struct nvram_parser *nvp) +{ + if (nvp->boardrev_found) + return; + + memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV, + strlen(BRCMF_FW_DEFAULT_BOARDREV)); + nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV); + nvp->nvram[nvp->nvram_len] = '\0'; + nvp->nvram_len++; +} + /* brcmf_nvram_strip :Takes a buffer of "=\n" lines read from a fil * and ending in a NUL. Removes carriage returns, empty lines, comment lines, * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. @@ -377,16 +398,21 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, if (nvp.state == END) break; } - if (nvp.multi_dev_v1) + if (nvp.multi_dev_v1) { + nvp.boardrev_found = false; brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr); - else if (nvp.multi_dev_v2) + } else if (nvp.multi_dev_v2) { + nvp.boardrev_found = false; brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr); + } if (nvp.nvram_len == 0) { kfree(nvp.nvram); return NULL; } + brcmf_fw_add_defaults(&nvp); + pad = nvp.nvram_len; *new_length = roundup(nvp.nvram_len + 1, 4); while (pad != *new_length) { From 2aec2c9d42aa9ac4b31583cf4e1c7774e040e57d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Mon, 11 Apr 2016 11:35:24 +0200 Subject: [PATCH 027/164] brcmfmac: fix p2p scan abort null pointer exception When p2p connection setup is performed without having ever done an escan a null pointer exception can occur. This is because the ifp to abort scanning is taken from escan struct while it was never initialized. Fix this by using the primary ifp for scan abort. The abort should still be performed and all scan related commands are performed on primary ifp. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index c2ac91df35ed..a70cda6c0592 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -1266,7 +1266,7 @@ static void brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) { struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_if *ifp = cfg->escan_info.ifp; + struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || From c56caa9db8abbbfb9e31325e0897705aa897db37 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Mon, 11 Apr 2016 11:35:25 +0200 Subject: [PATCH 028/164] brcmfmac: screening firmware event packet Firmware uses asynchronized events as a communication method to the host. The event packets are marked as ETH_P_LINK_CTL protocol type. For SDIO and PCIe bus, this kind of packets are delivered through virtual event channel not data channel. This patch adds a screening logic to make sure the event handler only processes the events coming from the correct channel. Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bus.h | 4 +- .../broadcom/brcm80211/brcmfmac/core.c | 46 +++++++++++++++---- .../broadcom/brcm80211/brcmfmac/core.h | 3 +- .../broadcom/brcm80211/brcmfmac/msgbuf.c | 42 +++++++++-------- .../broadcom/brcm80211/brcmfmac/sdio.c | 32 +++++++++---- .../broadcom/brcm80211/brcmfmac/usb.c | 2 +- 6 files changed, 90 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 8e02a478e889..31856eb57bc4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -216,7 +216,9 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec); /* Receive frame for delivery to OS. Callee disposes of rxp. */ -void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); +void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt); +/* Receive async event packet from firmware. Callee disposes of rxp. */ +void brcmf_rx_event(struct device *dev, struct sk_buff *rxp); /* Indication from bus module regarding presence/insertion of dongle. */ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index ff825cd7739e..8a91a517478b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -311,16 +311,17 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_fws_bus_blocked(drvr, state); } -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, + bool handle_event) { - skb->dev = ifp->ndev; - skb->protocol = eth_type_trans(skb, skb->dev); + skb->protocol = eth_type_trans(skb, ifp->ndev); if (skb->pkt_type == PACKET_MULTICAST) ifp->stats.multicast++; /* Process special event packets */ - brcmf_fweh_process_skb(ifp->drvr, skb); + if (handle_event) + brcmf_fweh_process_skb(ifp->drvr, skb); if (!(ifp->ndev->flags & IFF_UP)) { brcmu_pkt_buf_free_skb(skb); @@ -381,7 +382,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, /* validate flags and flow id */ if (flags == 0xFF) { brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -393,7 +394,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, if (rfi == NULL) { brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", flow_id); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -418,7 +419,7 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); return; } @@ -532,11 +533,11 @@ static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, netif_rx: skb_queue_walk_safe(&reorder_list, pkt, pnext) { __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, false); } } -void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) +void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -560,7 +561,32 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) if (rd->reorder) brcmf_rxreorder_process_info(ifp, rd->reorder, skb); else - brcmf_netif_rx(ifp, skb); + brcmf_netif_rx(ifp, skb, handle_evnt); +} + +void brcmf_rx_event(struct device *dev, struct sk_buff *skb) +{ + struct brcmf_if *ifp; + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + int ret; + + brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb); + + /* process and remove protocol-specific header */ + ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); + + if (ret || !ifp || !ifp->ndev) { + if (ret != -ENODATA && ifp) + ifp->stats.rx_errors++; + brcmu_pkt_buf_free_skb(skb); + return; + } + + skb->protocol = eth_type_trans(skb, ifp->ndev); + + brcmf_fweh_process_skb(ifp->drvr, skb); + brcmu_pkt_buf_free_skb(skb); } void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 7bdb6fef99c3..d3497e8bd59c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -225,7 +225,8 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, + bool handle_event); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 922966734a7f..3795354b7f12 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -1075,28 +1076,13 @@ static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf) } -static void -brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb, - u8 ifidx) -{ - struct brcmf_if *ifp; - - ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); - if (!ifp || !ifp->ndev) { - brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); - brcmu_pkt_buf_free_skb(skb); - return; - } - brcmf_netif_rx(ifp, skb); -} - - static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) { struct msgbuf_rx_event *event; u32 idx; u16 buflen; struct sk_buff *skb; + struct brcmf_if *ifp; event = (struct msgbuf_rx_event *)buf; idx = le32_to_cpu(event->msg.request_id); @@ -1116,7 +1102,19 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) skb_trim(skb, buflen); - brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx); + ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx); + if (!ifp || !ifp->ndev) { + brcmf_err("Received pkt for invalid ifidx %d\n", + event->msg.ifidx); + goto exit; + } + + skb->protocol = eth_type_trans(skb, ifp->ndev); + + brcmf_fweh_process_skb(ifp->drvr, skb); + +exit: + brcmu_pkt_buf_free_skb(skb); } @@ -1128,6 +1126,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) u16 data_offset; u16 buflen; u32 idx; + struct brcmf_if *ifp; brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1); @@ -1148,7 +1147,14 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) skb_trim(skb, buflen); - brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx); + ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx); + if (!ifp || !ifp->ndev) { + brcmf_err("Received pkt for invalid ifidx %d\n", + rx_complete->msg.ifidx); + brcmu_pkt_buf_free_skb(skb); + return; + } + brcmf_netif_rx(ifp, skb, false); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 48d7467d270e..4252fa82b89c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset(u8 *swheader) return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT); } +static inline bool brcmf_sdio_fromevntchan(u8 *swheader) +{ + u32 hdrvalue; + u8 ret; + + hdrvalue = *(u32 *)swheader; + ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT); + + return (ret == SDPCM_EVENT_CHANNEL); +} + static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, struct brcmf_sdio_hdrinfo *rd, enum brcmf_sdio_frmtype type) @@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) pfirst->len, pfirst->next, pfirst->prev); skb_unlink(pfirst, &bus->glom); - brcmf_rx_frame(bus->sdiodev->dev, pfirst); + if (brcmf_sdio_fromevntchan(pfirst->data)) + brcmf_rx_event(bus->sdiodev->dev, pfirst); + else + brcmf_rx_frame(bus->sdiodev->dev, pfirst, + false); bus->sdcnt.rxglompkts++; } @@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) __skb_trim(pkt, rd->len); skb_pull(pkt, rd->dat_offset); + if (pkt->len == 0) + brcmu_pkt_buf_free_skb(pkt); + else if (rd->channel == SDPCM_EVENT_CHANNEL) + brcmf_rx_event(bus->sdiodev->dev, pkt); + else + brcmf_rx_frame(bus->sdiodev->dev, pkt, + false); + /* prepare the descriptor for the next read */ rd->len = rd->len_nxtfrm << 4; rd->len_nxtfrm = 0; /* treat all packet as event if we don't know */ rd->channel = SDPCM_EVENT_CHANNEL; - - if (pkt->len == 0) { - brcmu_pkt_buf_free_skb(pkt); - continue; - } - - brcmf_rx_frame(bus->sdiodev->dev, pkt); } rxcount = maxframes - rxleft; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 869eb82db8b1..aa0b2a192faa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -514,7 +514,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { skb_put(skb, urb->actual_length); - brcmf_rx_frame(devinfo->dev, skb); + brcmf_rx_frame(devinfo->dev, skb, true); brcmf_usb_rx_refill(devinfo, req); } else { brcmu_pkt_buf_free_skb(skb); From bbd1f932e7c45ef173468ae2b49edefe52a8c835 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:26 +0200 Subject: [PATCH 029/164] brcmfmac: cleanup ampdu-rx host reorder code The code for ampdu-rx host reorder is related to the firmware signalling supported in BCDC protocol. This change moves the code to fwsignal module. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bcdc.c | 7 + .../broadcom/brcm80211/brcmfmac/core.c | 214 +----------------- .../broadcom/brcm80211/brcmfmac/core.h | 4 - .../broadcom/brcm80211/brcmfmac/fwsignal.c | 209 +++++++++++++++++ .../broadcom/brcm80211/brcmfmac/fwsignal.h | 1 + .../broadcom/brcm80211/brcmfmac/msgbuf.c | 4 + .../broadcom/brcm80211/brcmfmac/proto.h | 16 ++ 7 files changed, 239 insertions(+), 216 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 6af658e443e4..288fe906c80e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -351,6 +351,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, { } +static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp, + struct sk_buff *skb) +{ + brcmf_fws_rxreorder(ifp, skb); +} + int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc; @@ -372,6 +378,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode; drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer; drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer; + drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder; drvr->proto->pd = bcdc; drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 8a91a517478b..a30841bbc5a1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -40,19 +40,6 @@ #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950) -/* AMPDU rx reordering definitions */ -#define BRCMF_RXREORDER_FLOWID_OFFSET 0 -#define BRCMF_RXREORDER_MAXIDX_OFFSET 2 -#define BRCMF_RXREORDER_FLAGS_OFFSET 4 -#define BRCMF_RXREORDER_CURIDX_OFFSET 6 -#define BRCMF_RXREORDER_EXPIDX_OFFSET 8 - -#define BRCMF_RXREORDER_DEL_FLOW 0x01 -#define BRCMF_RXREORDER_FLUSH_ALL 0x02 -#define BRCMF_RXREORDER_CURIDX_VALID 0x04 -#define BRCMF_RXREORDER_EXPIDX_VALID 0x08 -#define BRCMF_RXREORDER_NEW_HOLE 0x10 - #define BRCMF_BSSIDX_INVALID -1 char *brcmf_ifname(struct brcmf_if *ifp) @@ -342,207 +329,11 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, netif_rx_ni(skb); } -static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, - u8 start, u8 end, - struct sk_buff_head *skb_list) -{ - /* initialize return list */ - __skb_queue_head_init(skb_list); - - if (rfi->pend_pkts == 0) { - brcmf_dbg(INFO, "no packets in reorder queue\n"); - return; - } - - do { - if (rfi->pktslots[start]) { - __skb_queue_tail(skb_list, rfi->pktslots[start]); - rfi->pktslots[start] = NULL; - } - start++; - if (start > rfi->max_idx) - start = 0; - } while (start != end); - rfi->pend_pkts -= skb_queue_len(skb_list); -} - -static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data, - struct sk_buff *pkt) -{ - u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; - struct brcmf_ampdu_rx_reorder *rfi; - struct sk_buff_head reorder_list; - struct sk_buff *pnext; - u8 flags; - u32 buf_size; - - flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET]; - flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET]; - - /* validate flags and flow id */ - if (flags == 0xFF) { - brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - rfi = ifp->drvr->reorder_flows[flow_id]; - if (flags & BRCMF_RXREORDER_DEL_FLOW) { - brcmf_dbg(INFO, "flow-%d: delete\n", - flow_id); - - if (rfi == NULL) { - brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", - flow_id); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx, - &reorder_list); - /* add the last packet */ - __skb_queue_tail(&reorder_list, pkt); - kfree(rfi); - ifp->drvr->reorder_flows[flow_id] = NULL; - goto netif_rx; - } - /* from here on we need a flow reorder instance */ - if (rfi == NULL) { - buf_size = sizeof(*rfi); - max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; - - buf_size += (max_idx + 1) * sizeof(pkt); - - /* allocate space for flow reorder info */ - brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n", - flow_id, max_idx); - rfi = kzalloc(buf_size, GFP_ATOMIC); - if (rfi == NULL) { - brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt, false); - return; - } - - ifp->drvr->reorder_flows[flow_id] = rfi; - rfi->pktslots = (struct sk_buff **)(rfi+1); - rfi->max_idx = max_idx; - } - if (flags & BRCMF_RXREORDER_NEW_HOLE) { - if (rfi->pend_pkts) { - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, - rfi->exp_idx, - &reorder_list); - WARN_ON(rfi->pend_pkts); - } else { - __skb_queue_head_init(&reorder_list); - } - rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; - rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; - rfi->pktslots[rfi->cur_idx] = pkt; - rfi->pend_pkts++; - brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n", - flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts); - } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) { - cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - - if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) { - /* still in the current hole */ - /* enqueue the current on the buffer chain */ - if (rfi->pktslots[cur_idx] != NULL) { - brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n"); - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); - rfi->pktslots[cur_idx] = NULL; - } - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - rfi->cur_idx = cur_idx; - brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n", - flow_id, cur_idx, exp_idx, rfi->pend_pkts); - - /* can return now as there is no reorder - * list to process. - */ - return; - } - if (rfi->exp_idx == cur_idx) { - if (rfi->pktslots[cur_idx] != NULL) { - brcmf_dbg(INFO, "error buffer pending..free it\n"); - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); - rfi->pktslots[cur_idx] = NULL; - } - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - - /* got the expected one. flush from current to expected - * and update expected - */ - brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n", - flow_id, cur_idx, exp_idx, rfi->pend_pkts); - - rfi->cur_idx = cur_idx; - rfi->exp_idx = exp_idx; - - brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx, - &reorder_list); - brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n", - flow_id, skb_queue_len(&reorder_list), - rfi->pend_pkts); - } else { - u8 end_idx; - - brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n", - flow_id, flags, rfi->cur_idx, rfi->exp_idx, - cur_idx, exp_idx); - if (flags & BRCMF_RXREORDER_FLUSH_ALL) - end_idx = rfi->exp_idx; - else - end_idx = exp_idx; - - /* flush pkts first */ - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, - &reorder_list); - - if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) { - __skb_queue_tail(&reorder_list, pkt); - } else { - rfi->pktslots[cur_idx] = pkt; - rfi->pend_pkts++; - } - rfi->exp_idx = exp_idx; - rfi->cur_idx = cur_idx; - } - } else { - /* explicity window move updating the expected index */ - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; - - brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n", - flow_id, flags, rfi->exp_idx, exp_idx); - if (flags & BRCMF_RXREORDER_FLUSH_ALL) - end_idx = rfi->exp_idx; - else - end_idx = exp_idx; - - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, - &reorder_list); - __skb_queue_tail(&reorder_list, pkt); - /* set the new expected idx */ - rfi->exp_idx = exp_idx; - } -netif_rx: - skb_queue_walk_safe(&reorder_list, pkt, pnext) { - __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt, false); - } -} - void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - struct brcmf_skb_reorder_data *rd; int ret; brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); @@ -557,9 +348,8 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) return; } - rd = (struct brcmf_skb_reorder_data *)skb->cb; - if (rd->reorder) - brcmf_rxreorder_process_info(ifp, rd->reorder, skb); + if (brcmf_proto_is_reorder_skb(skb)) + brcmf_proto_rxreorder(ifp, skb); else brcmf_netif_rx(ifp, skb, handle_evnt); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index d3497e8bd59c..394ae050b960 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -208,10 +208,6 @@ struct brcmf_if { u8 ipv6addr_idx; }; -struct brcmf_skb_reorder_data { - u8 *reorder; -}; - int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); /* Return pointer to interface name */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f82c9ab5480b..8a07687b46f8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len { }; #undef BRCMF_FWS_TLV_DEF +/* AMPDU rx reordering definitions */ +#define BRCMF_RXREORDER_FLOWID_OFFSET 0 +#define BRCMF_RXREORDER_MAXIDX_OFFSET 2 +#define BRCMF_RXREORDER_FLAGS_OFFSET 4 +#define BRCMF_RXREORDER_CURIDX_OFFSET 6 +#define BRCMF_RXREORDER_EXPIDX_OFFSET 8 + +#define BRCMF_RXREORDER_DEL_FLOW 0x01 +#define BRCMF_RXREORDER_FLUSH_ALL 0x02 +#define BRCMF_RXREORDER_CURIDX_VALID 0x04 +#define BRCMF_RXREORDER_EXPIDX_VALID 0x08 +#define BRCMF_RXREORDER_NEW_HOLE 0x10 + #ifdef DEBUG /* * brcmf_fws_tlv_names - array of tlv names. @@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp, return 0; } +static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, + u8 start, u8 end, + struct sk_buff_head *skb_list) +{ + /* initialize return list */ + __skb_queue_head_init(skb_list); + + if (rfi->pend_pkts == 0) { + brcmf_dbg(INFO, "no packets in reorder queue\n"); + return; + } + + do { + if (rfi->pktslots[start]) { + __skb_queue_tail(skb_list, rfi->pktslots[start]); + rfi->pktslots[start] = NULL; + } + start++; + if (start > rfi->max_idx) + start = 0; + } while (start != end); + rfi->pend_pkts -= skb_queue_len(skb_list); +} + +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) +{ + u8 *reorder_data; + u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; + struct brcmf_ampdu_rx_reorder *rfi; + struct sk_buff_head reorder_list; + struct sk_buff *pnext; + u8 flags; + u32 buf_size; + + reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder; + flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET]; + flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET]; + + /* validate flags and flow id */ + if (flags == 0xFF) { + brcmf_err("invalid flags...so ignore this packet\n"); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + rfi = ifp->drvr->reorder_flows[flow_id]; + if (flags & BRCMF_RXREORDER_DEL_FLOW) { + brcmf_dbg(INFO, "flow-%d: delete\n", + flow_id); + + if (rfi == NULL) { + brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", + flow_id); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx, + &reorder_list); + /* add the last packet */ + __skb_queue_tail(&reorder_list, pkt); + kfree(rfi); + ifp->drvr->reorder_flows[flow_id] = NULL; + goto netif_rx; + } + /* from here on we need a flow reorder instance */ + if (rfi == NULL) { + buf_size = sizeof(*rfi); + max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; + + buf_size += (max_idx + 1) * sizeof(pkt); + + /* allocate space for flow reorder info */ + brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n", + flow_id, max_idx); + rfi = kzalloc(buf_size, GFP_ATOMIC); + if (rfi == NULL) { + brcmf_err("failed to alloc buffer\n"); + brcmf_netif_rx(ifp, pkt, false); + return; + } + + ifp->drvr->reorder_flows[flow_id] = rfi; + rfi->pktslots = (struct sk_buff **)(rfi + 1); + rfi->max_idx = max_idx; + } + if (flags & BRCMF_RXREORDER_NEW_HOLE) { + if (rfi->pend_pkts) { + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, + rfi->exp_idx, + &reorder_list); + WARN_ON(rfi->pend_pkts); + } else { + __skb_queue_head_init(&reorder_list); + } + rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; + rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET]; + rfi->pktslots[rfi->cur_idx] = pkt; + rfi->pend_pkts++; + brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n", + flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts); + } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) { + cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET]; + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + + if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) { + /* still in the current hole */ + /* enqueue the current on the buffer chain */ + if (rfi->pktslots[cur_idx] != NULL) { + brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n"); + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); + rfi->pktslots[cur_idx] = NULL; + } + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + rfi->cur_idx = cur_idx; + brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n", + flow_id, cur_idx, exp_idx, rfi->pend_pkts); + + /* can return now as there is no reorder + * list to process. + */ + return; + } + if (rfi->exp_idx == cur_idx) { + if (rfi->pktslots[cur_idx] != NULL) { + brcmf_dbg(INFO, "error buffer pending..free it\n"); + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]); + rfi->pktslots[cur_idx] = NULL; + } + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + + /* got the expected one. flush from current to expected + * and update expected + */ + brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n", + flow_id, cur_idx, exp_idx, rfi->pend_pkts); + + rfi->cur_idx = cur_idx; + rfi->exp_idx = exp_idx; + + brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx, + &reorder_list); + brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n", + flow_id, skb_queue_len(&reorder_list), + rfi->pend_pkts); + } else { + u8 end_idx; + + brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n", + flow_id, flags, rfi->cur_idx, rfi->exp_idx, + cur_idx, exp_idx); + if (flags & BRCMF_RXREORDER_FLUSH_ALL) + end_idx = rfi->exp_idx; + else + end_idx = exp_idx; + + /* flush pkts first */ + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, + &reorder_list); + + if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) { + __skb_queue_tail(&reorder_list, pkt); + } else { + rfi->pktslots[cur_idx] = pkt; + rfi->pend_pkts++; + } + rfi->exp_idx = exp_idx; + rfi->cur_idx = cur_idx; + } + } else { + /* explicity window move updating the expected index */ + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET]; + + brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n", + flow_id, flags, rfi->exp_idx, exp_idx); + if (flags & BRCMF_RXREORDER_FLUSH_ALL) + end_idx = rfi->exp_idx; + else + end_idx = exp_idx; + + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx, + &reorder_list); + __skb_queue_tail(&reorder_list, pkt); + /* set the new expected idx */ + rfi->exp_idx = exp_idx; + } +netif_rx: + skb_queue_walk_safe(&reorder_list, pkt, pnext) { + __skb_unlink(pkt, &reorder_list); + brcmf_netif_rx(ifp, pkt, false); + } +} + void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) { struct brcmf_skb_reorder_data *rd; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index a36bac17eafd..ef0ad8597c8a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp); void brcmf_fws_del_interface(struct brcmf_if *ifp); void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked); +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb); #endif /* FWSIGNAL_H_ */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 3795354b7f12..8c064ab24b83 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -527,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, return -ENODEV; } +static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +{ +} static void brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid) @@ -1466,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode; drvr->proto->delete_peer = brcmf_msgbuf_delete_peer; drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer; + drvr->proto->rxreorder = brcmf_msgbuf_rxreorder; drvr->proto->pd = msgbuf; init_waitqueue_head(&msgbuf->ioctl_resp_wait); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index d55119d36755..57531f42190e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -22,6 +22,9 @@ enum proto_addr_mode { ADDR_DIRECT }; +struct brcmf_skb_reorder_data { + u8 *reorder; +}; struct brcmf_proto { int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, @@ -38,6 +41,7 @@ struct brcmf_proto { u8 peer[ETH_ALEN]); void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN]); + void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb); void *pd; }; @@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN]) { drvr->proto->add_tdls_peer(drvr, ifidx, peer); } +static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb) +{ + struct brcmf_skb_reorder_data *rd; + rd = (struct brcmf_skb_reorder_data *)skb->cb; + return !!rd->reorder; +} + +static inline void +brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +{ + ifp->drvr->proto->rxreorder(ifp, skb); +} #endif /* BRCMFMAC_PROTO_H */ From 9c349892ccc90c6de2baaa69cc78449f58082273 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:27 +0200 Subject: [PATCH 030/164] brcmfmac: revise handling events in receive path Move event handling out of brcmf_netif_rx() avoiding the need to pass a flag. This flag is only ever true for USB hosts as other interface use separate brcmf_rx_event() function. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/bus.h | 2 +- .../broadcom/brcm80211/brcmfmac/core.c | 24 +++++++++---------- .../broadcom/brcm80211/brcmfmac/core.h | 3 +-- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 8 +++---- .../broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 31856eb57bc4..2b246545647a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -216,7 +216,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec); /* Receive frame for delivery to OS. Callee disposes of rxp. */ -void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt); +void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event); /* Receive async event packet from firmware. Callee disposes of rxp. */ void brcmf_rx_event(struct device *dev, struct sk_buff *rxp); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index a30841bbc5a1..9b53555cf85c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -298,18 +298,11 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_fws_bus_blocked(drvr, state); } -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, - bool handle_event) +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) { - skb->protocol = eth_type_trans(skb, ifp->ndev); - if (skb->pkt_type == PACKET_MULTICAST) ifp->stats.multicast++; - /* Process special event packets */ - if (handle_event) - brcmf_fweh_process_skb(ifp->drvr, skb); - if (!(ifp->ndev->flags & IFF_UP)) { brcmu_pkt_buf_free_skb(skb); return; @@ -329,7 +322,7 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, netif_rx_ni(skb); } -void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) +void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -348,10 +341,17 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt) return; } - if (brcmf_proto_is_reorder_skb(skb)) + skb->protocol = eth_type_trans(skb, ifp->ndev); + + if (brcmf_proto_is_reorder_skb(skb)) { brcmf_proto_rxreorder(ifp, skb); - else - brcmf_netif_rx(ifp, skb, handle_evnt); + } else { + /* Process special event packets */ + if (handle_event) + brcmf_fweh_process_skb(ifp->drvr, skb); + + brcmf_netif_rx(ifp, skb); + } } void brcmf_rx_event(struct device *dev, struct sk_buff *skb) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 394ae050b960..241ee8d13e54 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -221,8 +221,7 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, - bool handle_event); +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 8a07687b46f8..5b30922b67ec 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -1668,7 +1668,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) /* validate flags and flow id */ if (flags == 0xFF) { brcmf_err("invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1680,7 +1680,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) if (rfi == NULL) { brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", flow_id); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1705,7 +1705,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { brcmf_err("failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); return; } @@ -1819,7 +1819,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) netif_rx: skb_queue_walk_safe(&reorder_list, pkt, pnext) { __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt, false); + brcmf_netif_rx(ifp, pkt); } } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 8c064ab24b83..68f1ce02f4bf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1157,7 +1157,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) brcmu_pkt_buf_free_skb(skb); return; } - brcmf_netif_rx(ifp, skb, false); + brcmf_netif_rx(ifp, skb); } From c462ebcdfe425a132aaba950d114ac32de3cdf44 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Mon, 11 Apr 2016 11:35:28 +0200 Subject: [PATCH 031/164] brcmfmac: create common function for handling brcmf_proto_hdrpull() In receive path brcmf_proto_hdrpull() needs to be called and handled similar in brcmf_rx_frame() and brcmf_rx_event(). Move that duplicated code in separate function. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/core.c | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9b53555cf85c..1b476d1fec2c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -322,26 +322,35 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) netif_rx_ni(skb); } +static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, + struct brcmf_if **ifp) +{ + int ret; + + /* process and remove protocol-specific header */ + ret = brcmf_proto_hdrpull(drvr, true, skb, ifp); + + if (ret || !(*ifp) || !(*ifp)->ndev) { + if (ret != -ENODATA && ifp) + (*ifp)->stats.rx_errors++; + brcmu_pkt_buf_free_skb(skb); + return -ENODATA; + } + + skb->protocol = eth_type_trans(skb, (*ifp)->ndev); + return 0; +} + void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - int ret; brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); - /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); - - if (ret || !ifp || !ifp->ndev) { - if (ret != -ENODATA && ifp) - ifp->stats.rx_errors++; - brcmu_pkt_buf_free_skb(skb); + if (brcmf_rx_hdrpull(drvr, skb, &ifp)) return; - } - - skb->protocol = eth_type_trans(skb, ifp->ndev); if (brcmf_proto_is_reorder_skb(skb)) { brcmf_proto_rxreorder(ifp, skb); @@ -359,21 +368,11 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb) struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - int ret; brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb); - /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); - - if (ret || !ifp || !ifp->ndev) { - if (ret != -ENODATA && ifp) - ifp->stats.rx_errors++; - brcmu_pkt_buf_free_skb(skb); + if (brcmf_rx_hdrpull(drvr, skb, &ifp)) return; - } - - skb->protocol = eth_type_trans(skb, ifp->ndev); brcmf_fweh_process_skb(ifp->drvr, skb); brcmu_pkt_buf_free_skb(skb); From c865a70098d9419d154f6d1ad97cd0150af968d1 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 11 Apr 2016 07:52:37 -0700 Subject: [PATCH 032/164] mwifiex: missing break statement This patch adds missing break statement at the end of PCIE_DEVICE_ID_MARVELL_88W8897 switch section. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index edf8b070f665..c28edbb73d8f 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2831,6 +2831,7 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) default: break; } + break; case PCIE_DEVICE_ID_MARVELL_88W8997: mwifiex_read_reg(adapter, 0x0c48, &revision_id); switch (revision_id) { From e87650bce9a5499f133341db99c9293bfb8a0282 Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Mon, 11 Apr 2016 07:52:38 -0700 Subject: [PATCH 033/164] mwifiex: add pcie usb/uart firmware download support This patch adds support for downloading usb/uart firmware for 8997 chipset by reading the chip version. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 17 +++++++++++++++-- drivers/net/wireless/marvell/mwifiex/pcie.h | 7 +++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index c28edbb73d8f..1d888b501e16 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2811,6 +2811,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) { int revision_id = 0; + int version; struct pcie_service_card *card = adapter->card; switch (card->dev->device) { @@ -2834,12 +2835,24 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) break; case PCIE_DEVICE_ID_MARVELL_88W8997: mwifiex_read_reg(adapter, 0x0c48, &revision_id); + mwifiex_read_reg(adapter, 0x0cd0, &version); + version &= 0x7; switch (revision_id) { case PCIE8997_V2: - strcpy(adapter->fw_name, PCIE8997_FW_NAME_V2); + if (version == CHIP_VER_PCIEUSB) + strcpy(adapter->fw_name, + PCIEUSB8997_FW_NAME_V2); + else + strcpy(adapter->fw_name, + PCIEUART8997_FW_NAME_V2); break; case PCIE8997_Z: - strcpy(adapter->fw_name, PCIE8997_FW_NAME_Z); + if (version == CHIP_VER_PCIEUSB) + strcpy(adapter->fw_name, + PCIEUSB8997_FW_NAME_Z); + else + strcpy(adapter->fw_name, + PCIEUART8997_FW_NAME_Z); break; default: break; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index cc7a5df903be..bbabfb01a10a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -32,8 +32,10 @@ #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" #define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin" #define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin" -#define PCIE8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" -#define PCIE8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin" +#define PCIEUART8997_FW_NAME_Z "mrvl/pcieuart8997_combo.bin" +#define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin" +#define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" +#define PCIEUSB8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin" #define PCIE_VENDOR_ID_MARVELL (0x11ab) #define PCIE_VENDOR_ID_V2_MARVELL (0x1b4b) @@ -45,6 +47,7 @@ #define PCIE8897_B0 0x1200 #define PCIE8997_Z 0x0 #define PCIE8997_V2 0x471 +#define CHIP_VER_PCIEUSB 0x2 /* Constants for Buffer Descriptor (BD) rings */ #define MWIFIEX_MAX_TXRX_BD 0x20 From b9db397879333c272f2bc888cd713773e7d2604f Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Mon, 11 Apr 2016 07:52:39 -0700 Subject: [PATCH 034/164] mwifiex: add default setting for pcie firmware download This patch adds default setting for pcie firmware download name in case that there are newer chipset version. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 3 +++ drivers/net/wireless/marvell/mwifiex/pcie.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 1d888b501e16..0c7937eb6b77 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2830,6 +2830,8 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME); break; default: + strcpy(adapter->fw_name, PCIE8897_DEFAULT_FW_NAME); + break; } break; @@ -2855,6 +2857,7 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) PCIEUART8997_FW_NAME_Z); break; default: + strcpy(adapter->fw_name, PCIE8997_DEFAULT_FW_NAME); break; } default: diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index bbabfb01a10a..5770b4396b21 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -30,8 +30,10 @@ #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" +#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin" #define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin" #define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin" +#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcieuart8997_combo_v2.bin" #define PCIEUART8997_FW_NAME_Z "mrvl/pcieuart8997_combo.bin" #define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin" #define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin" From c3ec0ff6425b86655aa34b5c6cb0f7b6d559c6b2 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 11 Apr 2016 07:52:40 -0700 Subject: [PATCH 035/164] mwifiex: do not wait on semaphore during card removal Host hang is observed if card is removed before firmware download gets completed. In this case, firmware will be failed to download and adapter structure gets freed. In other thread, mwifiex_remove_card() waits on semaphore until the firmware download fails. This wait is not necessary and may result in invalid adapter access. This patch uses down_trylock to return immediately so that hang issue won't occur. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 04b975cbb330..b459c70dc43f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1434,7 +1434,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) struct mwifiex_private *priv = NULL; int i; - if (down_interruptible(sem)) + if (down_trylock(sem)) goto exit_sem_err; if (!adapter) From bcc920e8f08336cbbdcdba7c4449c27137e6b4b9 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 11 Apr 2016 07:52:41 -0700 Subject: [PATCH 036/164] mwifiex: fix incorrect ht capability problem IEEE80211_CHAN_NO_HT40PLUS and IEEE80211_CHAN_NO_HT40PLUS channel flags tell if HT40 operation is allowed on a channel or not. This patch ensures ht_capability information is modified accordingly so that we don't end up creating a HT40 connection when it's not allowed for current regulatory domain. Signed-off-by: Amitkumar Karwar Signed-off-by: Cathy Luo Signed-off-by: Kalle Valo --- .../net/wireless/marvell/mwifiex/sta_ioctl.c | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index d8de432d46a2..8e0862657122 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -146,6 +146,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, size_t beacon_ie_len; struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; const struct cfg80211_bss_ies *ies; + int ret; rcu_read_lock(); ies = rcu_dereference(bss->ies); @@ -189,7 +190,48 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT) bss_desc->sensed_11h = true; - return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); + ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); + if (ret) + return ret; + + /* Update HT40 capability based on current channel information */ + if (bss_desc->bcn_ht_oper && bss_desc->bcn_ht_cap) { + u8 ht_param = bss_desc->bcn_ht_oper->ht_param; + u8 radio = mwifiex_band_to_radio_type(bss_desc->bss_band); + struct ieee80211_supported_band *sband = + priv->wdev.wiphy->bands[radio]; + int freq = ieee80211_channel_to_frequency(bss_desc->channel, + radio); + struct ieee80211_channel *chan = + ieee80211_get_channel(priv->adapter->wiphy, freq); + + switch (ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) { + sband->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } else { + sband->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) { + sband->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + } else { + sband->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40; + } + break; + } + } + + return 0; } void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) From 84349698f05dc7ed6df6772d43175eb3703ed8dc Mon Sep 17 00:00:00 2001 From: Vishal Thanki Date: Thu, 7 Apr 2016 23:37:12 +0200 Subject: [PATCH 037/164] mwifiex: fix the incorrect WARN_ON during suspend During system suspend, there is a kernel WARNING issued if there is a pending command present. By marking the wait queue disabled after calling the command completion routine fixes it. Signed-off-by: Vishal Thanki Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index a12adee776c6..6f0470646483 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1009,9 +1009,9 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); /* Cancel current cmd */ if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { - adapter->curr_cmd->wait_q_enabled = false; adapter->cmd_wait_q.status = -1; mwifiex_complete_cmd(adapter, adapter->curr_cmd); + adapter->curr_cmd->wait_q_enabled = false; /* no recycle probably wait for response */ } /* Cancel all pending command */ From 14e105cd4085c7bbf42f0eef8c677ad6c7d78a83 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:21 +0300 Subject: [PATCH 038/164] ath10k: fix checkpatch warnings related to spaces Fix checkpatch warnings about use of spaces with operators: spaces preferred around that '*' (ctx:VxV) This has been recently added to checkpatch. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 6 +++--- drivers/net/wireless/ath/ath10k/ce.h | 2 +- drivers/net/wireless/ath/ath10k/core.h | 6 +++--- drivers/net/wireless/ath/ath10k/debug.h | 2 +- drivers/net/wireless/ath/ath10k/htc.h | 4 ++-- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/mac.c | 8 ++++---- drivers/net/wireless/ath/ath10k/targaddrs.h | 2 +- drivers/net/wireless/ath/ath10k/thermal.h | 2 +- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 4 ++-- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 18 +++++++++--------- 13 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 7212802eb327..9fb8d7472d18 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1050,11 +1050,11 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, * * For the lack of a better place do the check here. */ - BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_10X_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); - BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC > + BUILD_BUG_ON(2 * TARGET_TLV_NUM_MSDU_DESC > (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); ce_state->ar = ar; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 25cafcfd6b12..dfc098606bee 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -408,7 +408,7 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) /* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */ #define CE_RING_DELTA(nentries_mask, fromidx, toidx) \ - (((int)(toidx)-(int)(fromidx)) & (nentries_mask)) + (((int)(toidx) - (int)(fromidx)) & (nentries_mask)) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) #define CE_RING_IDX_ADD(nentries_mask, idx, num) \ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d85b99164212..e6f889df1e0d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -44,8 +44,8 @@ #define ATH10K_SCAN_ID 0 #define WMI_READY_TIMEOUT (5 * HZ) -#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ) -#define ATH10K_CONNECTION_LOSS_HZ (3*HZ) +#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) +#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) #define ATH10K_NUM_CHANS 39 /* Antenna noise floor */ @@ -334,7 +334,7 @@ struct ath10k_sta { #endif }; -#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) +#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) enum ath10k_beacon_state { ATH10K_BEACON_SCHEDULED = 0, diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 6206edd7c49f..75c89e3625ef 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -57,7 +57,7 @@ enum ath10k_dbg_aggr_mode { }; /* FIXME: How to calculate the buffer size sanely? */ -#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) +#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024) extern unsigned int ath10k_debug_mask; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index e70aa38e6e05..cc827185d3e9 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -297,10 +297,10 @@ struct ath10k_htc_svc_conn_resp { #define ATH10K_NUM_CONTROL_TX_BUFFERS 2 #define ATH10K_HTC_MAX_LEN 4096 #define ATH10K_HTC_MAX_CTRL_MSG_LEN 256 -#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ) +#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ) #define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \ sizeof(struct ath10k_htc_hdr)) -#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ) +#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ) struct ath10k_htc_ep { struct ath10k_htc *htc; diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 17a3008d9ab1..ee79512b1fcc 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -208,7 +208,7 @@ int ath10k_htt_init(struct ath10k *ar) return 0; } -#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ) +#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ) static int ath10k_htt_verify_version(struct ath10k_htt *htt) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c30a3944b612..4300410ecddf 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3846,7 +3846,7 @@ static int ath10k_scan_stop(struct ath10k *ar) goto out; } - ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ); + ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ); if (ret == 0) { ath10k_warn(ar, "failed to receive scan abortion completion: timed out\n"); ret = -ETIMEDOUT; @@ -3926,7 +3926,7 @@ static int ath10k_start_scan(struct ath10k *ar, if (ret) return ret; - ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ); + ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ); if (ret == 0) { ret = ath10k_scan_stop(ar); if (ret) @@ -6168,7 +6168,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, return ret; } -#define ATH10K_ROC_TIMEOUT_HZ (2*HZ) +#define ATH10K_ROC_TIMEOUT_HZ (2 * HZ) static int ath10k_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -6232,7 +6232,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, goto exit; } - ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ); + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ); if (ret == 0) { ath10k_warn(ar, "failed to switch to channel for roc scan\n"); diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 361f143b019c..8e24099fa936 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -438,7 +438,7 @@ Fw Mode/SubMode Mask ((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED)) #define HI_DEV_LPL_TYPE_GET(_devix) \ (HOST_INTEREST->hi_pwr_save_flags & ((HI_PWR_SAVE_LPL_DEV_MASK) << \ - (HI_PWR_SAVE_LPL_DEV0_LSB + (_devix)*2))) + (HI_PWR_SAVE_LPL_DEV0_LSB + (_devix) * 2))) #define HOST_INTEREST_SMPS_IS_ALLOWED() \ ((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK)) diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h index c9223e9e962f..3abb97f63b1e 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.h +++ b/drivers/net/wireless/ath/ath10k/thermal.h @@ -20,7 +20,7 @@ #define ATH10K_QUIET_PERIOD_MIN 25 #define ATH10K_QUIET_START_OFFSET 10 #define ATH10K_HWMON_NAME_LEN 15 -#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ) +#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ) #define ATH10K_THERMAL_THROTTLE_MAX 100 struct ath10k_thermal { diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 9369411a9ac0..c503ff601a54 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -166,7 +166,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, (mapped == expect_mapped || test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); - }), 3*HZ); + }), 3 * HZ); if (time_left == 0) return -ETIMEDOUT; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index dd678590531a..b8aa6000573c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -968,8 +968,8 @@ enum wmi_tlv_service { #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \ ((svc_id) < (len) && \ - __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ - BIT((svc_id)%(sizeof(u32)))) + __le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \ + BIT((svc_id) % (sizeof(u32)))) #define SVCMAP(x, y, len) \ do { \ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index e8d9a3e5c2df..d64e8681898d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1808,7 +1808,7 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) ret = -ESHUTDOWN; (ret != -EAGAIN); - }), 3*HZ); + }), 3 * HZ); if (ret) dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index c83e1e39f8cc..378f2998cd5a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -405,8 +405,8 @@ static inline char *wmi_service_name(int service_id) #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \ ((svc_id) < (len) && \ - __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ - BIT((svc_id)%(sizeof(u32)))) + __le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \ + BIT((svc_id) % (sizeof(u32)))) #define SVCMAP(x, y, len) \ do { \ @@ -1309,7 +1309,7 @@ enum wmi_10x_event_id { WMI_10X_PDEV_TPC_CONFIG_EVENTID, WMI_10X_GPIO_INPUT_EVENTID, - WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1, + WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID - 1, }; enum wmi_10_2_cmd_id { @@ -2042,8 +2042,8 @@ struct wmi_10x_service_ready_event { struct wlan_host_mem_req mem_reqs[0]; } __packed; -#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) -#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) +#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) +#define WMI_UNIFIED_READY_TIMEOUT_HZ (5 * HZ) struct wmi_ready_event { __le32 sw_version; @@ -4389,14 +4389,14 @@ enum wmi_vdev_subtype_10_4 { /* * Indicates that AP VDEV uses hidden ssid. only valid for * AP/GO */ -#define WMI_VDEV_START_HIDDEN_SSID (1<<0) +#define WMI_VDEV_START_HIDDEN_SSID (1 << 0) /* * Indicates if robust management frame/management frame * protection is enabled. For GO/AP vdevs, it indicates that * it may support station/client associations with RMF enabled. * For STA/client vdevs, it indicates that sta will * associate with AP with RMF enabled. */ -#define WMI_VDEV_START_PMF_ENABLED (1<<1) +#define WMI_VDEV_START_PMF_ENABLED (1 << 1) struct wmi_p2p_noa_descriptor { __le32 type_count; /* 255: continuous schedule, 0: reserved */ @@ -5342,7 +5342,7 @@ enum wmi_sta_ps_param_pspoll_count { #define WMI_UAPSD_AC_TYPE_TRIG 1 #define WMI_UAPSD_AC_BIT_MASK(ac, type) \ - ((type == WMI_UAPSD_AC_TYPE_DELI) ? (1<<(ac<<1)) : (1<<((ac<<1)+1))) + ((type == WMI_UAPSD_AC_TYPE_DELI) ? (1 << (ac << 1)) : (1 << ((ac << 1) + 1))) enum wmi_sta_ps_param_uapsd { WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), @@ -5757,7 +5757,7 @@ struct wmi_rate_set { * the rates are filled from least significant byte to most * significant byte. */ - __le32 rates[(MAX_SUPPORTED_RATES/4)+1]; + __le32 rates[(MAX_SUPPORTED_RATES / 4) + 1]; } __packed; struct wmi_rate_set_arg { From beeb1a302f783b0ddeabafebf03f30d589df15eb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:35 +0300 Subject: [PATCH 039/164] ath10k: prefer kernel type 'u64' over 'u_int64_t' Fixes checkpatch warnings: drivers/net/wireless/ath/ath10k/htt.h:1477: Prefer kernel type 'u64' over 'u_int64_t' drivers/net/wireless/ath/ath10k/htt.h:1480: Prefer kernel type 'u64' over 'u_int64_t' Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 60bd9fe4b2d9..ee7c8f8f8073 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1475,10 +1475,10 @@ union htt_rx_pn_t { u32 pn24; /* TKIP or CCMP: 48-bit PN */ - u_int64_t pn48; + u64 pn48; /* WAPI: 128-bit PN */ - u_int64_t pn128[2]; + u64 pn128[2]; }; struct htt_cmd { From c178da58c7aa73d1442ce10cc61df41224115d19 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:13:49 +0300 Subject: [PATCH 040/164] ath10k: prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() Fixes checkpatch warnings: drivers/net/wireless/ath/ath10k/mac.c:452: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() drivers/net/wireless/ath/ath10k/mac.c:455: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() drivers/net/wireless/ath/ath10k/txrx.c:133: Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4300410ecddf..76ea1ccb59c5 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -449,10 +449,10 @@ static int ath10k_mac_vif_update_wep_key(struct ath10k_vif *arvif, lockdep_assert_held(&ar->conf_mutex); list_for_each_entry(peer, &ar->peers, list) { - if (!memcmp(peer->addr, arvif->vif->addr, ETH_ALEN)) + if (ether_addr_equal(peer->addr, arvif->vif->addr)) continue; - if (!memcmp(peer->addr, arvif->bssid, ETH_ALEN)) + if (ether_addr_equal(peer->addr, arvif->bssid)) continue; if (peer->keys[key->keyidx] == key) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index c503ff601a54..8c7086989a71 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -130,7 +130,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, list_for_each_entry(peer, &ar->peers, list) { if (peer->vdev_id != vdev_id) continue; - if (memcmp(peer->addr, addr, ETH_ALEN)) + if (!ether_addr_equal(peer->addr, addr)) continue; return peer; From 8f4ffb7de9630065040e8142d651708e85eeb863 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:14:02 +0300 Subject: [PATCH 041/164] ath10k: prefer ether_addr_copy() over memcpy() Fixes checkpatch warning: drivers/net/wireless/ath/ath10k/wmi.c:5800: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index d64e8681898d..7eb40f54fdb5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5827,9 +5827,8 @@ ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs, bssids->num_bssid = __cpu_to_le32(arg->n_bssids); for (i = 0; i < arg->n_bssids; i++) - memcpy(&bssids->bssid_list[i], - arg->bssids[i].bssid, - ETH_ALEN); + ether_addr_copy(bssids->bssid_list[i].addr, + arg->bssids[i].bssid); ptr += sizeof(*bssids); ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids; From 4d16544d0bde4b19da30789a8715635fd9c3889d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 13 Apr 2016 14:14:16 +0300 Subject: [PATCH 042/164] ath10k: fix parenthesis alignment Found by checkpatch: drivers/net/wireless/ath/ath10k/mac.c:6800: Alignment should match open parent Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 76ea1ccb59c5..d9d98bf22b3e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6797,7 +6797,7 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf) + u64 tsf) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); From 0a233c98a8e933a65aec07663d3a2953c7642bbc Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:05 +0100 Subject: [PATCH 043/164] mwifiex: scan: simplify dereference of bss_desc fields given this structure: struct foo { struct bar { int baz; } } these accesses are equivalent: (*(foo->bar)).baz foo->bar->baz Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 98 ++++++++++----------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 624b0a95c64e..99026cef3179 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -121,8 +121,8 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id == WLAN_EID_RSN))) { + if (bss_desc->bcn_rsn_ie && + bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN) { iebody = (struct ie_body *) (((u8 *) bss_desc->bcn_rsn_ie->data) + RSN_GTK_OUI_OFFSET); @@ -148,9 +148,9 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC))) { + if (bss_desc->bcn_wpa_ie && + bss_desc->bcn_wpa_ie->vend_hdr.element_id == + WLAN_EID_VENDOR_SPECIFIC) { iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; oui = &mwifiex_wpa_oui[cipher][0]; ret = mwifiex_search_oui_in_ie(iebody, oui); @@ -181,8 +181,8 @@ mwifiex_is_bss_wapi(struct mwifiex_private *priv, { if (priv->sec_info.wapi_enabled && (bss_desc->bcn_wapi_ie && - ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY))) { + bss_desc->bcn_wapi_ie->ieee_hdr.element_id == + WLAN_EID_BSS_AC_ACCESS_DELAY)) { return true; } return false; @@ -197,12 +197,12 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != - WLAN_EID_RSN)) && + !priv->sec_info.wpa2_enabled && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && !priv->sec_info.encryption_mode && !bss_desc->privacy) { return true; } @@ -233,9 +233,10 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)) + !priv->sec_info.wpa2_enabled && + (bss_desc->bcn_wpa_ie && + bss_desc->bcn_wpa_ie->vend_hdr.element_id == + WLAN_EID_VENDOR_SPECIFIC) /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -245,12 +246,10 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, "info: %s: WPA:\t" "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", @@ -269,11 +268,10 @@ static bool mwifiex_is_bss_wpa2(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { - if (!priv->sec_info.wep_enabled && - !priv->sec_info.wpa_enabled && + if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled && - ((bss_desc->bcn_rsn_ie) && - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) { + (bss_desc->bcn_rsn_ie && + bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN)) { /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -282,12 +280,10 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, "info: %s: WPA2:\t" "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", @@ -308,11 +304,11 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && !priv->sec_info.encryption_mode && bss_desc->privacy) { return true; } @@ -329,23 +325,21 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && + (!bss_desc->bcn_wpa_ie || + bss_desc->bcn_wpa_ie->vend_hdr.element_id != + WLAN_EID_VENDOR_SPECIFIC) && + (!bss_desc->bcn_rsn_ie || + bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { mwifiex_dbg(priv->adapter, INFO, "info: %s: dynamic\t" "WEP: wpa_ie=%#x wpa2_ie=%#x\t" "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, priv->sec_info.encryption_mode, bss_desc->privacy); return true; @@ -464,10 +458,10 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t" "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, (priv->sec_info.wep_enabled) ? "e" : "d", (priv->sec_info.wpa_enabled) ? "e" : "d", (priv->sec_info.wpa2_enabled) ? "e" : "d", From 38329568c3f7075c7751984a65e16a9c7fc186bd Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:06 +0100 Subject: [PATCH 044/164] mwifiex: scan: factor out has_ieee_hdr/has_vendor_hdr Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 52 +++++++++------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 99026cef3179..e926d3ab7286 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -76,6 +76,18 @@ static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ }; +static bool +has_ieee_hdr(struct ieee_types_generic *ie, u8 key) +{ + return (ie && ie->ieee_hdr.element_id == key); +} + +static bool +has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key) +{ + return (ie && ie->vend_hdr.element_id == key); +} + /* * This function parses a given IE for a given OUI. * @@ -121,8 +133,7 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (bss_desc->bcn_rsn_ie && - bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN) { + if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { iebody = (struct ie_body *) (((u8 *) bss_desc->bcn_rsn_ie->data) + RSN_GTK_OUI_OFFSET); @@ -148,9 +159,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) struct ie_body *iebody; u8 ret = MWIFIEX_OUI_NOT_PRESENT; - if (bss_desc->bcn_wpa_ie && - bss_desc->bcn_wpa_ie->vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC) { + if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) { iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; oui = &mwifiex_wpa_oui[cipher][0]; ret = mwifiex_search_oui_in_ie(iebody, oui); @@ -180,11 +189,8 @@ mwifiex_is_bss_wapi(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc) { if (priv->sec_info.wapi_enabled && - (bss_desc->bcn_wapi_ie && - bss_desc->bcn_wapi_ie->ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY)) { + has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY)) return true; - } return false; } @@ -198,11 +204,8 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && !priv->sec_info.encryption_mode && !bss_desc->privacy) { return true; } @@ -234,9 +237,7 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (bss_desc->bcn_wpa_ie && - bss_desc->bcn_wpa_ie->vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC) + has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -270,8 +271,7 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled && - (bss_desc->bcn_rsn_ie && - bss_desc->bcn_rsn_ie->ieee_hdr.element_id == WLAN_EID_RSN)) { + has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) { /* * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy @@ -304,11 +304,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && !priv->sec_info.encryption_mode && bss_desc->privacy) { return true; } @@ -325,11 +322,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, { if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled && - (!bss_desc->bcn_wpa_ie || - bss_desc->bcn_wpa_ie->vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC) && - (!bss_desc->bcn_rsn_ie || - bss_desc->bcn_rsn_ie->ieee_hdr.element_id != WLAN_EID_RSN) && + !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && + !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { mwifiex_dbg(priv->adapter, INFO, "info: %s: dynamic\t" From 2ccf7cef0cf984241d0b6932ed1cfb1e0d6587d5 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:07 +0100 Subject: [PATCH 045/164] mwifiex: scan: simplify ternary operators using gnu extension "x ? x : y" can be simplified as "x ? : y" https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals Reviewed-by: Julian Calaby Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index e926d3ab7286..11f8a608b8af 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -900,14 +900,11 @@ mwifiex_config_scan(struct mwifiex_private *priv, /* Set the BSS type scan filter, use Adapter setting if unset */ scan_cfg_out->bss_mode = - (user_scan_in->bss_mode ? (u8) user_scan_in-> - bss_mode : (u8) adapter->scan_mode); + (u8)(user_scan_in->bss_mode ?: adapter->scan_mode); /* Set the number of probes to send, use Adapter setting if unset */ - num_probes = - (user_scan_in->num_probes ? user_scan_in-> - num_probes : adapter->scan_probes); + num_probes = user_scan_in->num_probes ?: adapter->scan_probes; /* * Set the BSSID filter to the incoming configuration, From 679b687bc96ddf2ef077ca4aa755924032bd18a8 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:08 +0100 Subject: [PATCH 046/164] mwifiex: scan: factor out dbg_security_flags merge copy/paste code Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 74 +++++++-------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 11f8a608b8af..11d57185a090 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -76,6 +76,27 @@ static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ }; +static void +_dbg_security_flags(int log_level, const char *func, const char *desc, + struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + _mwifiex_dbg(priv->adapter, log_level, + "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n", + func, desc, + bss_desc->bcn_wpa_ie ? + bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, + bss_desc->bcn_rsn_ie ? + bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, + priv->sec_info.wep_enabled ? "e" : "d", + priv->sec_info.wpa_enabled ? "e" : "d", + priv->sec_info.wpa2_enabled ? "e" : "d", + priv->sec_info.encryption_mode, + bss_desc->privacy); +} +#define dbg_security_flags(mask, desc, priv, bss_desc) \ + _dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc) + static bool has_ieee_hdr(struct ieee_types_generic *ie, u8 key) { @@ -243,19 +264,7 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, * LinkSys WRT54G && bss_desc->privacy */ ) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "WPA", priv, bss_desc); return true; } return false; @@ -276,19 +285,7 @@ mwifiex_is_bss_wpa2(struct mwifiex_private *priv, * Privacy bit may NOT be set in some APs like * LinkSys WRT54G && bss_desc->privacy */ - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA2:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "WAP2", priv, bss_desc); return true; } return false; @@ -325,17 +322,7 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) && !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) && priv->sec_info.encryption_mode && bss_desc->privacy) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: dynamic\t" - "WEP: wpa_ie=%#x wpa2_ie=%#x\t" - "EncMode=%#x privacy=%#x\n", - __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - priv->sec_info.encryption_mode, - bss_desc->privacy); + dbg_security_flags(INFO, "dynamic", priv, bss_desc); return true; } return false; @@ -448,18 +435,7 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, } /* Security doesn't match */ - mwifiex_dbg(adapter, ERROR, - "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t" - "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", - __func__, - bss_desc->bcn_wpa_ie ? - bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0, - bss_desc->bcn_rsn_ie ? - bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, bss_desc->privacy); + dbg_security_flags(ERROR, "failed", priv, bss_desc); return -1; } From 948ad6b34943a1247653392d59bcfc9896da8fe7 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:09 +0100 Subject: [PATCH 047/164] mwifiex: scan: replace pointer arithmetic with array access improves readability Reviewed-by: Julian Calaby Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 11d57185a090..753d92a731af 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1055,27 +1055,24 @@ mwifiex_config_scan(struct mwifiex_private *priv, chan_idx++) { channel = user_scan_in->chan_list[chan_idx].chan_number; - (scan_chan_list + chan_idx)->chan_number = channel; + scan_chan_list[chan_idx].chan_number = channel; radio_type = user_scan_in->chan_list[chan_idx].radio_type; - (scan_chan_list + chan_idx)->radio_type = radio_type; + scan_chan_list[chan_idx].radio_type = radio_type; scan_type = user_scan_in->chan_list[chan_idx].scan_type; if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap |= (MWIFIEX_PASSIVE_SCAN | MWIFIEX_HIDDEN_SSID_REPORT); else - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap &= ~MWIFIEX_PASSIVE_SCAN; if (*filtered_scan) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap + scan_chan_list[chan_idx].chan_scan_mode_bitmap |= MWIFIEX_DISABLE_CHAN_FILT; if (user_scan_in->chan_list[chan_idx].scan_time) { @@ -1090,9 +1087,9 @@ mwifiex_config_scan(struct mwifiex_private *priv, scan_dur = adapter->active_scan_time; } - (scan_chan_list + chan_idx)->min_scan_time = + scan_chan_list[chan_idx].min_scan_time = cpu_to_le16(scan_dur); - (scan_chan_list + chan_idx)->max_scan_time = + scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(scan_dur); } From c70ca8cb9a7c6722d5bb6d428b6571921998c48d Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:10 +0100 Subject: [PATCH 048/164] mwifiex: factor out mwifiex_cancel_pending_scan_cmd Releasing the scan_pending lock in mwifiex_check_next_scan_command introduces a short window where pending scan commands can be removed or added before removing them all in mwifiex_cancel_pending_scan_cmd. I think this is safe, since the worst thing to happen is that a pending scan cmd is removed by the command handler. Adding new scan commands is not possible while one is pending, see scan_processing flag. Since all commands are removed from the queue anyway, we don't care if some commands are removed by a different code path earlier, the final state remains the same. I assume, that the critical section needed for the check has been extended over clearing the pending scan queue out of convenience. The lock was already held and releasing it and grab it again was just more work. It doesn't seem to be necessary because of concurrency. Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 43 +++++++++---------- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/scan.c | 23 +++------- .../wireless/marvell/mwifiex/sta_cmdresp.c | 13 +----- 4 files changed, 27 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 6f0470646483..f5af525485f6 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -991,6 +991,23 @@ mwifiex_cmd_timeout_func(unsigned long function_context) adapter->if_ops.card_reset(adapter); } +void +mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter) +{ + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; + unsigned long flags; + + /* Cancel all pending scan command */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + cmd_node->wait_q_enabled = false; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); +} + /* * This function cancels all the pending commands. * @@ -1029,16 +1046,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); if (adapter->scan_processing) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); @@ -1070,9 +1078,8 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + struct cmd_ctrl_node *cmd_node = NULL; unsigned long cmd_flags; - unsigned long scan_pending_q_flags; struct mwifiex_private *priv; int i; @@ -1094,17 +1101,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) mwifiex_recycle_cmd_node(adapter, cmd_node); } - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); + mwifiex_cancel_pending_scan_cmd(adapter); if (adapter->scan_processing) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index a159fbef20cd..6306654d2799 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1042,6 +1042,7 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); +void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node); diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 753d92a731af..36cc9cca95fc 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -619,8 +619,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, int ret = 0; struct mwifiex_chan_scan_param_set *tmp_chan_list; struct mwifiex_chan_scan_param_set *start_chan; - struct cmd_ctrl_node *cmd_node, *tmp_node; - unsigned long flags; u32 tlv_idx, rates_size, cmd_no; u32 total_scan_time; u32 done_early; @@ -777,16 +775,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, sizeof(struct mwifiex_ie_types_header) + rates_size; if (ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, - list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); + mwifiex_cancel_pending_scan_cmd(adapter); break; } } @@ -1949,12 +1938,13 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node, *tmp_node; + struct cmd_ctrl_node *cmd_node; unsigned long flags; spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); if (list_empty(&adapter->scan_pending_q)) { spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); @@ -1976,13 +1966,10 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) } } else if ((priv->scan_aborting && !priv->scan_request) || priv->scan_block) { - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 434b9776db45..d18c7979d723 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -44,7 +44,6 @@ static void mwifiex_process_cmdresp_error(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; struct mwifiex_adapter *adapter = priv->adapter; struct host_cmd_ds_802_11_ps_mode_enh *pm; unsigned long flags; @@ -71,17 +70,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, break; case HostCmd_CMD_802_11_SCAN: case HostCmd_CMD_802_11_SCAN_EXT: - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + mwifiex_cancel_pending_scan_cmd(adapter); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); adapter->scan_processing = false; From 85abfb1239ecda32222c161670667c7b2f6832be Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 10 Mar 2016 09:44:11 +0100 Subject: [PATCH 049/164] mwifiex: make mwifiex_insert_cmd_to_free_q local static after factoring out mwifiex_cancel_pending_scan_cmd the function is not called outside of cmdevt file moved function to head of file to avoid forward declaration, also moved mwifiex_recycle_cmd_node since they are very similar Signed-off-by: Andreas Fenkart Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 82 +++++++++---------- drivers/net/wireless/marvell/mwifiex/main.h | 2 - 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index f5af525485f6..6bc2011d8609 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -104,6 +104,47 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, } } +/* + * This function returns a command to the command free queue. + * + * The function also calls the completion callback if required, before + * cleaning the command node and re-inserting it into the free queue. + */ +static void +mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + unsigned long flags; + + if (!cmd_node) + return; + + if (cmd_node->wait_q_enabled) + mwifiex_complete_cmd(adapter, cmd_node); + /* Clean the node */ + mwifiex_clean_cmd_node(adapter, cmd_node); + + /* Insert node into cmd_free_q */ + spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); + list_add_tail(&cmd_node->list, &adapter->cmd_free_q); + spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); +} + +/* This function reuses a command node. */ +void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, + struct cmd_ctrl_node *cmd_node) +{ + struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; + + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + + atomic_dec(&adapter->cmd_pending); + mwifiex_dbg(adapter, CMD, + "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", + le16_to_cpu(host_cmd->command), + atomic_read(&adapter->cmd_pending)); +} + /* * This function sends a host command to the firmware. * @@ -613,47 +654,6 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, return ret; } -/* - * This function returns a command to the command free queue. - * - * The function also calls the completion callback if required, before - * cleaning the command node and re-inserting it into the free queue. - */ -void -mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - unsigned long flags; - - if (!cmd_node) - return; - - if (cmd_node->wait_q_enabled) - mwifiex_complete_cmd(adapter, cmd_node); - /* Clean the node */ - mwifiex_clean_cmd_node(adapter, cmd_node); - - /* Insert node into cmd_free_q */ - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->cmd_free_q); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -} - -/* This function reuses a command node. */ -void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; - - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - - atomic_dec(&adapter->cmd_pending); - mwifiex_dbg(adapter, CMD, - "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", - le16_to_cpu(host_cmd->command), - atomic_read(&adapter->cmd_pending)); -} - /* * This function queues a command to the command pending queue. * diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 6306654d2799..63069dd8b8e8 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1044,8 +1044,6 @@ void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); -void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node); From c157863d99797f6fed60e6e56d53afeb0bc3b436 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:42 -0400 Subject: [PATCH 050/164] rtl8xxxu: Reorder parts of init code to match the 8192eu vendor code flow In order to debug 8192eu support, reorder some init code to match the flow of the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e36fda8c1ad3..d67b88665194 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7592,6 +7592,26 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; + /* RFSW Control - clear bit 14 ?? */ + if (priv->rtl_chip != RTL8723B) + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); + /* 0x07000760 */ + if (priv->rtl_chip == RTL8192E) { + val32 = 0; + } else { + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + } + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ + if (priv->rtl_chip != RTL8192E) + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); + + priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, + RF6052_REG_MODE_AG); + /* * Chip specific quirks */ @@ -7653,21 +7673,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - /* RFSW Control - clear bit 14 ?? */ - if (priv->rtl_chip != RTL8723B) - rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); - /* 0x07000760 */ - val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); - /* 0x860[6:5]= 00 - why? - this sets antenna B */ - rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66F60210); - - priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_MODE_AG); - /* * Set RX page boundary */ From 59b24dad20d41c00b51f5ca549a9e83a53671bc9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:43 -0400 Subject: [PATCH 051/164] rtl8xxxu: Reorg more code to match the flow of the 8192eu vendor driver This further reorganizes the init code flow to match that of the 8192eu vendor driver. This helps diffing the register write log against that of the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 109 +++++++++--------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index d67b88665194..c6c41ba2a511 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7468,34 +7468,39 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; } - dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); if (!macpower) { - ret = priv->fops->llt_init(priv, TX_TOTAL_PAGE_NUM); - if (ret) { - dev_warn(dev, "%s: LLT table init failed\n", __func__); - goto exit; - } + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; - /* - * Presumably this is for 8188EU as well - * Enable TX report and TX report timer - */ - if (priv->rtl_chip == RTL8723B) { - val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); - val8 |= TX_REPORT_CTRL_TIMER_ENABLE; - rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); - /* Set MAX RPT MACID */ - rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, 0x02); - /* TX report Timer. Unit: 32us */ - rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, 0xcdf0); + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - /* tmp ps ? */ - val8 = rtl8xxxu_read8(priv, 0xa3); - val8 &= 0xf8; - rtl8xxxu_write8(priv, 0xa3, val8); - } + val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); } + ret = rtl8xxxu_init_queue_priority(priv); + dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); + if (ret) + goto exit; + + /* + * Set RX page boundary + */ + if (priv->rtl_chip == RTL8723B) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); + else if (priv->rtl_chip == RTL8192E) + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); + else + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + ret = rtl8xxxu_download_firmware(priv); dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); if (ret) @@ -7634,22 +7639,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } if (!macpower) { - if (priv->ep_tx_normal_queue) - val8 = TX_PAGE_NUM_NORM_PQ; - else - val8 = 0; - - rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - - val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; - - if (priv->ep_tx_high_queue) - val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); - if (priv->ep_tx_low_queue) - val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); - - rtl8xxxu_write32(priv, REG_RQPN, val32); - /* * Set TX buffer boundary */ @@ -7668,20 +7657,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_TDECTRL + 1, val8); } - ret = rtl8xxxu_init_queue_priority(priv); - dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); - if (ret) - goto exit; - - /* - * Set RX page boundary - */ - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); - else if (priv->rtl_chip == RTL8192E) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); - else - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); /* * Transfer page size is always 128 */ @@ -7693,6 +7668,34 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); rtl8xxxu_write8(priv, REG_PBP, val8); + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + ret = priv->fops->llt_init(priv, TX_TOTAL_PAGE_NUM); + if (ret) { + dev_warn(dev, "%s: LLT table init failed\n", __func__); + goto exit; + } + + /* + * Presumably this is for 8188EU as well + * Enable TX report and TX report timer + */ + if (priv->rtl_chip == RTL8723B) { + val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL); + val8 |= TX_REPORT_CTRL_TIMER_ENABLE; + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); + /* Set MAX RPT MACID */ + rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL + 1, 0x02); + /* TX report Timer. Unit: 32us */ + rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, 0xcdf0); + + /* tmp ps ? */ + val8 = rtl8xxxu_read8(priv, 0xa3); + val8 &= 0xf8; + rtl8xxxu_write8(priv, 0xa3, val8); + } + } + /* * Unit in 8 bytes, not obvious what it is used for */ From 89c2a097df34362a5e8373749a2f81ca2503b598 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:44 -0400 Subject: [PATCH 052/164] rtl8xxxu: Implement generic init_queue_reserved_page() function Longer term we should switch all the chips over to use this function instead of the random chip specific ifdef hacks. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 75 +++++++++++++++---- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 9 +++ .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 2 +- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c6c41ba2a511..a9290d469759 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7439,6 +7439,60 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32); } +static void rtl8xxxu_old_init_queue_reserved_page(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; + + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); + + val32 = (TX_PAGE_NUM_PUBQ << RQPN_PUB_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); +} + +static void rtl8xxxu_init_queue_reserved_page(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_fileops *fops = priv->fops; + u32 hq, lq, nq, eq, pubq; + u32 val32; + + hq = 0; + lq = 0; + nq = 0; + eq = 0; + pubq = 0; + + if (priv->ep_tx_high_queue) + hq = fops->page_num_hi; + if (priv->ep_tx_low_queue) + lq = fops->page_num_lo; + if (priv->ep_tx_normal_queue) + nq = fops->page_num_norm; + + val32 = (nq << RQPN_NPQ_SHIFT) | (eq << RQPN_EPQ_SHIFT); + rtl8xxxu_write32(priv, REG_RQPN_NPQ, val32); + + pubq = fops->total_page_num - hq - lq - nq; + + val32 = RQPN_LOAD; + val32 |= (hq << RQPN_HI_PQ_SHIFT); + val32 |= (lq << RQPN_LO_PQ_SHIFT); + val32 |= (pubq << RQPN_PUB_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); +} + static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; @@ -7469,21 +7523,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } if (!macpower) { - if (priv->ep_tx_normal_queue) - val8 = TX_PAGE_NUM_NORM_PQ; + if (priv->fops->total_page_num) + rtl8xxxu_init_queue_reserved_page(priv); else - val8 = 0; - - rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); - - val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; - - if (priv->ep_tx_high_queue) - val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); - if (priv->ep_tx_low_queue) - val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); - - rtl8xxxu_write32(priv, REG_RQPN, val32); + rtl8xxxu_old_init_queue_reserved_page(priv); } ret = rtl8xxxu_init_queue_priority(priv); @@ -9751,6 +9794,10 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, .mactable = rtl8192e_mac_init_table, + .total_page_num = TX_TOTAL_PAGE_NUM_8192E, + .page_num_hi = TX_PAGE_NUM_HI_PQ_8192E, + .page_num_lo = TX_PAGE_NUM_LO_PQ_8192E, + .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192E, }; static struct usb_device_id dev_table[] = { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 48a80fa9eac2..4545e10bede1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -49,6 +49,11 @@ #define TX_PAGE_NUM_LO_PQ 0x02 #define TX_PAGE_NUM_NORM_PQ 0x02 +#define TX_PAGE_NUM_PUBQ_8192E 0xe7 +#define TX_PAGE_NUM_HI_PQ_8192E 0x08 +#define TX_PAGE_NUM_LO_PQ_8192E 0x0c +#define TX_PAGE_NUM_NORM_PQ_8192E 0x00 + #define RTL_FW_PAGE_SIZE 4096 #define RTL8XXXU_FIRMWARE_POLL_MAX 1000 @@ -1304,4 +1309,8 @@ struct rtl8xxxu_fileops { u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; struct rtl8xxxu_reg8val *mactable; + u8 total_page_num; + u8 page_num_hi; + u8 page_num_lo; + u8 page_num_norm; }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index bb08a3939e46..a2cff2273e72 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -387,7 +387,7 @@ #define REG_RQPN 0x0200 #define RQPN_HI_PQ_SHIFT 0 #define RQPN_LO_PQ_SHIFT 8 -#define RQPN_NORM_PQ_SHIFT 16 +#define RQPN_PUB_PQ_SHIFT 16 #define RQPN_LOAD BIT(31) #define REG_FIFOPAGE 0x0204 From 0486e80b2a447fc94687505ca106091b15e61651 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:45 -0400 Subject: [PATCH 053/164] rtl8xxxu: Reorder chip quirks to follow flow of 8192eu driver Another flow order change to match the vendor driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a9290d469759..9e9d3e351e65 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7660,27 +7660,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); - /* - * Chip specific quirks - */ - if (priv->rtl_chip == RTL8723A) { - /* Fix USB interface interference issue */ - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x8d); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - } else { - val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); - val32 |= TXDMA_OFFSET_DROP_DATA_EN; - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); - } - if (!macpower) { /* * Set TX buffer boundary @@ -7719,6 +7698,27 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; } + /* + * Chip specific quirks + */ + if (priv->rtl_chip == RTL8723A) { + /* Fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + } else { + val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); + val32 |= TXDMA_OFFSET_DROP_DATA_EN; + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); + } + /* * Presumably this is for 8188EU as well * Enable TX report and TX report timer From 2e7c7b347d93e41a2c4adf9350da6a351f585810 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:46 -0400 Subject: [PATCH 054/164] rtl8xxxu: Do not set REG_PBP on 8192eu The vendor driver does not set REG_PBP on 8192eu. Whether this is due to the device not supporting it or simply an oversight in the vendor driver is not clear. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 9e9d3e351e65..36bd4fc1aee8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7688,7 +7688,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) else val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); - rtl8xxxu_write8(priv, REG_PBP, val8); + if (priv->rtl_chip != RTL8192E) + rtl8xxxu_write8(priv, REG_PBP, val8); dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); if (!macpower) { From b816901b3d20e9e2941b130139d440953c3b0ba8 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:47 -0400 Subject: [PATCH 055/164] rtl8xxxu: Do not init FPGA0_TX_INFO on 8192eu Like the 8723bu, the vendor driver does not set FPGA0_TX_INFO for 8192eu in the init sequence. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 36bd4fc1aee8..ed8c594dd10d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7641,7 +7641,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) goto exit; /* RFSW Control - clear bit 14 ?? */ - if (priv->rtl_chip != RTL8723B) + if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); /* 0x07000760 */ if (priv->rtl_chip == RTL8192E) { From 5bdb6b0859887bad5c83639ca9fb2d5fd0d5a8a0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:48 -0400 Subject: [PATCH 056/164] rtl8xxxu: Do not try to set REG_LEDCFG2 on 8192eu Presumably 8192eu devices do not have leds, so do not enable them. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ed8c594dd10d..99cf4aa97c0b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7880,9 +7880,11 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) priv->fops->set_tx_power(priv, 1, false); /* Let the 8051 take control of antenna setting */ - val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); - val8 |= LEDCFG2_DPDT_SELECT; - rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + if (priv->rtl_chip != RTL8192E) { + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + } rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, 0xff); From 57e42a21a941decc15f1198db64fe3959b066096 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:49 -0400 Subject: [PATCH 057/164] rtl8xxxu: Implment rtl8192e_set_tx_power() 8192eu is a 2T part, so setting TX power for path A only, as done by rtl8723bu_set_tx_power() is not sufficient. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 78 ++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 99cf4aa97c0b..7ab009fc5ecc 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2555,6 +2555,82 @@ rtl8723b_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs); } +static void +rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u32 val32, ofdm, mcs; + u8 cck, ofdmbase, mcsbase; + int group, tx_idx; + + tx_idx = 0; + group = rtl8723b_channel_to_group(channel); + + cck = priv->cck_tx_power_index_A[group]; + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); + val32 &= 0xffff00ff; + val32 |= (cck << 8); + rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xff; + val32 |= ((cck << 8) | (cck << 16) | (cck << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_A[group]; + ofdmbase += priv->ofdm_tx_power_diff[tx_idx].a; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm); + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_A[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[tx_idx++].a; + else + mcsbase += priv->ht20_tx_power_diff[tx_idx++].a; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs); + + if (priv->tx_paths > 1) { + cck = priv->cck_tx_power_index_B[group]; + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32); + val32 &= 0xff; + val32 |= ((cck << 8) | (cck << 16) | (cck << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xffffff00; + val32 |= cck; + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_B[group]; + ofdmbase += priv->ofdm_tx_power_diff[tx_idx].b; + ofdm = ofdmbase | ofdmbase << 8 | + ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_B[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[tx_idx++].b; + else + mcsbase += priv->ht20_tx_power_diff[tx_idx++].b; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs); + } +} + static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, enum nl80211_iftype linktype) { @@ -9784,7 +9860,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .parse_rx_desc = rtl8723bu_parse_rx_desc, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, - .set_tx_power = rtl8723b_set_tx_power, + .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 128, From 55c0b6ae1e7b1a402f23ca8fafa1874f854b4834 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:50 -0400 Subject: [PATCH 058/164] rtl8xxxu: Use has_s0s1 for REG_S0S1 issues only Instead use tx_desc_size() to distinguish between gen1 (8723a/8192c/8188c) and gen2 (8723b/8192e) parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7ab009fc5ecc..8b0b6c92793c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2758,7 +2758,8 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) } else if (val32 & SYS_CFG_TYPE_ID) { bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); bonding &= HPON_FSM_BONDING_MASK; - if (priv->fops->has_s0s1) { + if (priv->fops->tx_desc_size == + sizeof(struct rtl8xxxu_txdesc40)) { if (bonding == HPON_FSM_BONDING_1T2R) { sprintf(priv->chip_name, "8191EU"); priv->rf_paths = 2; @@ -7993,7 +7994,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * This should enable thermal meter */ - if (priv->fops->has_s0s1) + if (priv->fops->tx_desc_size == sizeof(struct rtl8xxxu_txdesc40)) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER_8723B, 0x37cf8); else @@ -9867,7 +9868,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), - .has_s0s1 = 1, + .has_s0s1 = 0, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, From 2cb79eb74f08f0217a6c4f21ddc42627016771ff Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:51 -0400 Subject: [PATCH 059/164] rtl8xxxu: byteswap the entire RX descriptor for 24 byte RX descriptors This shouldn't affect little endian system, but may have prevented the driver working on big endian systems for devices with the larger 24 byte RX descriptors. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 8b0b6c92793c..6545012a49ad 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8832,7 +8832,13 @@ static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, { struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; struct rtl8723au_phy_stats *phy_stats; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; + int i; + + for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); @@ -8873,7 +8879,13 @@ static int rtl8723bu_parse_rx_desc(struct rtl8xxxu_priv *priv, struct rtl8723bu_rx_desc *rx_desc = (struct rtl8723bu_rx_desc *)skb->data; struct rtl8723au_phy_stats *phy_stats; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; + int i; + + for (i = 0; i < (sizeof(struct rtl8723bu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); skb_pull(skb, sizeof(struct rtl8723bu_rx_desc)); @@ -8967,12 +8979,7 @@ static void rtl8xxxu_rx_complete(struct urb *urb) struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); struct device *dev = &priv->udev->dev; - __le32 *_rx_desc_le = (__le32 *)skb->data; - u32 *_rx_desc = (u32 *)skb->data; - int rx_type, i; - - for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) - _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); + int rx_type; skb_put(skb, urb->actual_length); From a49c7ce183cd78c9786348f8dea3d8027cee8177 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:52 -0400 Subject: [PATCH 060/164] rtl8xxxu: Name RX descriptor types rxdesc16/rxdesc24 This caught a bug where too little memory was allocated for RX urbs for parts using 24 byte RX descriptors Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 38 +++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6545012a49ad..4b309a60f5a1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8826,21 +8826,22 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *work) } } -static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, +static int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; + struct rtl8xxxu_rxdesc16 *rx_desc = + (struct rtl8xxxu_rxdesc16 *)skb->data; struct rtl8723au_phy_stats *phy_stats; __le32 *_rx_desc_le = (__le32 *)skb->data; u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; int i; - for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc16) / sizeof(u32)); i++) _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); - skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); + skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc16)); phy_stats = (struct rtl8723au_phy_stats *)skb->data; @@ -8872,22 +8873,22 @@ static int rtl8723au_parse_rx_desc(struct rtl8xxxu_priv *priv, return RX_TYPE_DATA_PKT; } -static int rtl8723bu_parse_rx_desc(struct rtl8xxxu_priv *priv, +static int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct rtl8723bu_rx_desc *rx_desc = - (struct rtl8723bu_rx_desc *)skb->data; + struct rtl8xxxu_rxdesc24 *rx_desc = + (struct rtl8xxxu_rxdesc24 *)skb->data; struct rtl8723au_phy_stats *phy_stats; __le32 *_rx_desc_le = (__le32 *)skb->data; u32 *_rx_desc = (u32 *)skb->data; int drvinfo_sz, desc_shift; int i; - for (i = 0; i < (sizeof(struct rtl8723bu_rx_desc) / sizeof(u32)); i++) + for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++) _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); - skb_pull(skb, sizeof(struct rtl8723bu_rx_desc)); + skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24)); phy_stats = (struct rtl8723au_phy_stats *)skb->data; @@ -9018,14 +9019,15 @@ static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, { struct sk_buff *skb; int skb_size; - int ret; + int ret, rx_desc_sz; - skb_size = sizeof(struct rtl8xxxu_rx_desc) + RTL_RX_BUFFER_SIZE; + rx_desc_sz = priv->fops->rx_desc_size; + skb_size = rx_desc_sz + RTL_RX_BUFFER_SIZE; skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL); if (!skb) return -ENOMEM; - memset(skb->data, 0, sizeof(struct rtl8xxxu_rx_desc)); + memset(skb->data, 0, rx_desc_sz); usb_fill_bulk_urb(&rx_urb->urb, priv->udev, priv->pipe_in, skb->data, skb_size, rtl8xxxu_rx_complete, skb); usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor); @@ -9779,7 +9781,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .llt_init = rtl8xxxu_init_llt_table, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, - .parse_rx_desc = rtl8723au_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, .set_tx_power = rtl8723a_set_tx_power, @@ -9789,6 +9791,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -9806,7 +9809,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, - .parse_rx_desc = rtl8723bu_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, @@ -9818,6 +9821,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .has_s0s1 = 1, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, @@ -9837,7 +9841,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .llt_init = rtl8xxxu_init_llt_table, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, - .parse_rx_desc = rtl8723au_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, .set_tx_power = rtl8723a_set_tx_power, @@ -9847,6 +9851,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16), .adda_1t_init = 0x0b1b25a0, .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, @@ -9865,7 +9870,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .llt_init = rtl8xxxu_auto_llt_table, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, - .parse_rx_desc = rtl8723bu_parse_rx_desc, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, .set_tx_power = rtl8192e_set_tx_power, @@ -9875,6 +9880,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .has_s0s1 = 0, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 4545e10bede1..2f0709ee0cb3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -101,7 +101,7 @@ enum rtl8xxxu_rx_type { RX_TYPE_ERROR = -1 }; -struct rtl8xxxu_rx_desc { +struct rtl8xxxu_rxdesc16 { #ifdef __LITTLE_ENDIAN u32 pktlen:14; u32 crc32:1; @@ -237,7 +237,7 @@ struct rtl8xxxu_rx_desc { #endif }; -struct rtl8723bu_rx_desc { +struct rtl8xxxu_rxdesc24 { #ifdef __LITTLE_ENDIAN u32 pktlen:14; u32 crc32:1; @@ -1303,6 +1303,7 @@ struct rtl8xxxu_fileops { u16 mbox_ext_reg; char mbox_ext_width; char tx_desc_size; + char rx_desc_size; char has_s0s1; u32 adda_1t_init; u32 adda_1t_path_on; From fe62171fb5cac42d0ff665e61b2735965e9efd45 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:53 -0400 Subject: [PATCH 061/164] rtl8xxxu: Remove misleading warning from rtl8192eu_phy_iqcalibrate() No actual code flow change, but no need to warn about something that isn't a prioblem. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4b309a60f5a1..71d375c5ffa3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5897,8 +5897,6 @@ static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__); if (priv->rf_paths > 1) { - dev_warn(dev, "%s: Path B ongoing\n", __func__); - /* Path A into standby */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x10000); From 15f9dc99237df4b29f000464c35925bb0a56ead7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:54 -0400 Subject: [PATCH 062/164] rtl8xxxu: Remove unused 8723bu path B IQ calibration code The 8723bu is a combo WiFi/BT dongle, and path B is not used for WiFi, so no point in calibrating it. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 76 +------------------ 1 file changed, 3 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 71d375c5ffa3..c355d27a26d0 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4988,50 +4988,6 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) return result; } -#ifdef RTL8723BU_PATH_B -static int rtl8723bu_iqk_path_b(struct rtl8xxxu_priv *priv) -{ - u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, path_sel; - int result = 0; - - path_sel = rtl8xxxu_read32(priv, REG_S0S1_PATH_SWITCH); - - val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); - val32 &= 0x000000ff; - rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - - /* One shot, path B LOK & IQK */ - rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000002); - rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000000); - - mdelay(1); - - /* Check failed */ - reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); - reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); - reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); - reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); - reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); - - if (!(reg_eac & BIT(31)) && - ((reg_eb4 & 0x03ff0000) != 0x01420000) && - ((reg_ebc & 0x03ff0000) != 0x00420000)) - result |= 0x01; - else - goto out; - - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) && - (((reg_ecc & 0x03ff0000) >> 16) != 0x36)) - result |= 0x02; - else - dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", - __func__); -out: - return result; -} -#endif - static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) { u32 reg_eac, reg_e94, reg_e9c; @@ -5619,20 +5575,6 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); -#ifdef RTL8723BU_PATH_B - /* Set RF mode to standby Path B */ - if (priv->tx_paths > 1) - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000); -#endif - -#if 0 - /* Page B init */ - rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x0f600000); - - if (priv->tx_paths > 1) - rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, 0x0f600000); -#endif - /* * RX IQ calibration setting for 8723B D cut large current issue * when leaving IPS @@ -5662,12 +5604,6 @@ static void rtl8723bu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); -#if 0 /* Only needed in restore case, we may need this when going to suspend */ - priv->RFCalibrateInfo.TxLOK[RF_A] = - rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_TXM_IDAC); -#endif - val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); result[t][0] = (val32 >> 16) & 0x3ff; @@ -6209,15 +6145,9 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_ED, val32); rtl8xxxu_write_rfreg(priv, RF_A, 0x43, 0x300bd); - if (priv->rf_paths > 1) { - dev_dbg(dev, "%s: beware 2T not yet supported\n", __func__); -#ifdef RTL8723BU_PATH_B - if (RF_Path == 0x0) //S1 - ODM_SetIQCbyRFpath(pDM_Odm, 0); - else //S0 - ODM_SetIQCbyRFpath(pDM_Odm, 1); -#endif - } + if (priv->rf_paths > 1) + dev_dbg(dev, "%s: 8723BU 2T not supported\n", __func__); + rtl8xxxu_prepare_calibrate(priv, 0); } From 9068308ad185a3c2c5d7beb77146b6df7b96b9c6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:55 -0400 Subject: [PATCH 063/164] rtl8xxxu: Correctly mask what was read from REG_CCK0_AFE_SETTING The old code incorrectly wiped out bits 0-23 by mistake when setting the RX path for 1T parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c355d27a26d0..d0330a8f32fb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,7 +3814,7 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); - val32 &= 0xff000000; + val32 &= 0x00ffffff; val32 |= 0x45000000; rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); From bd8fe40cc4f30f3f0982345135d97a676d1d3652 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:56 -0400 Subject: [PATCH 064/164] rtl8xxxu: Use descriptive bits for setting RX paths for 1T2R parts This reduce the use of magic values a little. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 +++- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index d0330a8f32fb..3c45ad0bdbca 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,8 +3814,10 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 &= ~CCK0_AFE_RX_MASK; val32 &= 0x00ffffff; - val32 |= 0x45000000; + val32 |= 0x40000000; + val32 |= CCK0_AFE_RX_ANT_B; rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index a2cff2273e72..e7709a5bcb3a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -882,6 +882,10 @@ #define CCK0_SIDEBAND BIT(4) #define REG_CCK0_AFE_SETTING 0x0a04 +#define CCK0_AFE_RX_MASK 0x0f000000 +#define CCK0_AFE_RX_ANT_AB BIT(24) +#define CCK0_AFE_RX_ANT_A 0 +#define CCK0_AFE_RX_ANT_B (BIT(24) | BIT(26)) #define REG_CONFIG_ANT_A 0x0b68 #define REG_CONFIG_ANT_B 0x0b6c From cb8772504a27d7ada67840efe5439f3df3621e13 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:57 -0400 Subject: [PATCH 065/164] rtl8xxxu: Split rtl8xxxu_init_phy_bb() into device specific functions This reduces the if () clutter. Longer term it probably makes sense to split this between gen1 (8723au/8188cu/8192cu) and gen2 (8192eu/8723bu) devices. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 134 ++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3c45ad0bdbca..43359a394503 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3717,76 +3717,36 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, return 0; } -/* - * Most of this is black magic retrieved from the old rtl8723au driver - */ -static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u8 val8; u16 val16; u32 val32; - /* - * Todo: The vendor driver maintains a table of PHY register - * addresses, which is initialized here. Do we need this? - */ + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + udelay(2); + val8 |= AFE_PLL_320_ENABLE; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + udelay(2); - if (priv->rtl_chip == RTL8723B) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | - SYS_FUNC_DIO_RF; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); + udelay(2); - rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); - } else if (priv->rtl_chip == RTL8192E) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | - SYS_FUNC_DIO_RF; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - } else { - val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); - udelay(2); - val8 |= AFE_PLL_320_ENABLE; - rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); - udelay(2); + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); - udelay(2); - - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - } - - if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { - /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ - val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); - val32 &= ~AFE_XTAL_RF_GATE; - if (priv->has_bluetooth) - val32 &= ~AFE_XTAL_BT_GATE; - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); - } + val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + val32 &= ~AFE_XTAL_RF_GATE; + if (priv->has_bluetooth) + val32 &= ~AFE_XTAL_BT_GATE; + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); /* 6. 0x1f[7:0] = 0x07 */ val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - if (priv->rtl_chip == RTL8723B) { - /* - * Why? - */ - rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); - rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); - rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); - } else if (priv->rtl_chip == RTL8192E) { - val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); - val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | - SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); - rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); - val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; - rtl8xxxu_write8(priv, REG_RF_CTRL, val8); - rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); - } else if (priv->hi_pa) + if (priv->hi_pa) rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); else if (priv->tx_paths == 2) rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); @@ -3796,6 +3756,60 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); +} + +static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + /* Why? */ + rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); + rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); + rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); +} + +static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF | + SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); +} + +/* + * Most of this is black magic retrieved from the old rtl8723au driver + */ +static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u32 val32; + + priv->fops->init_phy_bb(priv); if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* @@ -9709,6 +9723,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, + .init_phy_bb = rtl8723au_init_phy_bb, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9736,6 +9751,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .power_off = rtl8723bu_power_off, .reset_8051 = rtl8723bu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8723bu_init_phy_bb, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, @@ -9769,6 +9785,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, + .init_phy_bb = rtl8723au_init_phy_bb, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9798,6 +9815,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8192eu_init_phy_bb, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 2f0709ee0cb3..28874fae750e 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1284,6 +1284,7 @@ struct rtl8xxxu_fileops { void (*power_off) (struct rtl8xxxu_priv *priv); void (*reset_8051) (struct rtl8xxxu_priv *priv); int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page); + void (*init_phy_bb) (struct rtl8xxxu_priv *priv); void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv); void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv); void (*config_channel) (struct ieee80211_hw *hw); From ade0dedde11923e1d1f17bd81395b627821ad49c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:58 -0400 Subject: [PATCH 066/164] rtl8xxxu: Load AGC table before patching for 1T2R parts This should get the order right and avoid patching something that is later overwritten. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 43359a394503..21275078b6e2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3811,6 +3811,20 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) priv->fops->init_phy_bb(priv); + if (priv->rtl_chip == RTL8723B) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); + else if (priv->rtl_chip == RTL8192E) { + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, + rtl8xxx_agc_8192eu_std_table); + } else if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* * For 1T2R boards, patch the registers. @@ -3871,20 +3885,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); } - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->rtl_chip == RTL8192E) { - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_std_table); - } else if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); - if (priv->has_xtalk) { val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); From c82f8d113e354588fe3351b10e0c1ea154f5c600 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:58:59 -0400 Subject: [PATCH 067/164] rtl8xxxu: Move loading of AGC table to device specific function This moves the loading of the AGC table into init_phy_bb() and reduces the if() clutter. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 21275078b6e2..baa53a14a30d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3756,6 +3756,11 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) if (priv->rtl_chip == RTL8188C && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); } static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3777,6 +3782,8 @@ static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_SYS_FUNC, 0xe3); rtl8xxxu_write8(priv, REG_AFE_XTAL_CTRL + 1, 0x80); rtl8xxxu_init_phy_regs(priv, rtl8723b_phy_1t_init_table); + + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); } static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3799,6 +3806,11 @@ static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; rtl8xxxu_write8(priv, REG_RF_CTRL, val8); rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_std_table); } /* @@ -3811,20 +3823,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) priv->fops->init_phy_bb(priv); - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8723bu_table); - else if (priv->rtl_chip == RTL8192E) { - if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, - rtl8xxx_agc_8192eu_std_table); - } else if (priv->hi_pa) - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); - else - rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); - if (priv->tx_paths == 1 && priv->rx_paths == 2) { /* * For 1T2R boards, patch the registers. From b84cac16f0f42b9b3f6210984c939f712c471026 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:00 -0400 Subject: [PATCH 068/164] rtl8xxxu: REG_LDOA15_CTRL is only used on gen1 parts Move setting it to rtl8723au_init_phy_bb() Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index baa53a14a30d..4ef8a05d924f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3719,7 +3719,7 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8; + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; u16 val16; u32 val32; @@ -3761,6 +3761,13 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); else rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + + ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; + ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); + ldohci12 = 0x57; + lpldo = 1; + val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15; + rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); } static void rtl8723bu_init_phy_bb(struct rtl8xxxu_priv *priv) @@ -3818,7 +3825,7 @@ static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv) */ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u8 val8; u32 val32; priv->fops->init_phy_bb(priv); @@ -3893,17 +3900,6 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); } - if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) { - ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; - ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); - ldohci12 = 0x57; - lpldo = 1; - val32 = (lpldo << 24) | (ldohci12 << 16) | - (ldov12d << 8) | ldoa15; - - rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); - } - if (priv->rtl_chip == RTL8192E) rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x000f81fb); From 24e8e7ec331d04c329048d3b85034c54d23f4fab Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:01 -0400 Subject: [PATCH 069/164] rtl8xxxu: Store device specific TRXFF boundary in the fileops This removes another case of ugly if () clutter Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 11 +++++------ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4ef8a05d924f..ef93f6285aa2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7552,12 +7552,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Set RX page boundary */ - if (priv->rtl_chip == RTL8723B) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3f7f); - else if (priv->rtl_chip == RTL8192E) - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x3cff); - else - rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, priv->fops->trxff_boundary); ret = rtl8xxxu_download_firmware(priv); dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); @@ -9735,6 +9730,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .trxff_boundary = 0x27ff, .mactable = rtl8723a_mac_init_table, }; @@ -9767,6 +9763,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, + .trxff_boundary = 0x3f7f, .mactable = rtl8723b_mac_init_table, }; @@ -9797,6 +9794,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_1t_path_on = 0x0bdb25a0, .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, + .trxff_boundary = 0x27ff, .mactable = rtl8723a_mac_init_table, }; @@ -9828,6 +9826,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, .adda_2t_path_on_b = 0x0fc01616, + .trxff_boundary = 0x3cff, .mactable = rtl8192e_mac_init_table, .total_page_num = TX_TOTAL_PAGE_NUM_8192E, .page_num_hi = TX_PAGE_NUM_HI_PQ_8192E, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 28874fae750e..f66e20d4449b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1310,6 +1310,7 @@ struct rtl8xxxu_fileops { u32 adda_1t_path_on; u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; + u16 trxff_boundary; struct rtl8xxxu_reg8val *mactable; u8 total_page_num; u8 page_num_hi; From a77372069119061313b4815d119b5fbde0676dbb Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:02 -0400 Subject: [PATCH 070/164] rtl8xxxu: Do not backup RF_MODE_AG when it's never being used This was expired by the vendor driver, but we never ended up using the backed up value. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 3 --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index ef93f6285aa2..c12a4c8cb63a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7667,9 +7667,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); - priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, - RF6052_REG_MODE_AG); - if (!macpower) { /* * Set TX buffer boundary diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index f66e20d4449b..b87cd2bef53c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1228,7 +1228,6 @@ struct rtl8xxxu_priv { u8 rf_paths; u8 rx_paths; u8 tx_paths; - u32 rf_mode_ag[2]; u32 rege94; u32 rege9c; u32 regeb4; From 9b323ee97af6e0c982b57ba0a21db14728dd4476 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:03 -0400 Subject: [PATCH 071/164] rtl8xxxu: Make PBP tuning a fileops parameter Rather than scattering the code with #ifdefs, use the fileops structure to hold device specific PBP values. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 17 ++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 ++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c12a4c8cb63a..3e3ca28d5709 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7687,14 +7687,11 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) } /* - * Transfer page size is always 128 + * The vendor drivers set PBP for all devices, except 8192e. + * There is no explanation for this in any of the sources. */ - if (priv->rtl_chip == RTL8723B) - val8 = (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_RX_SHIFT) | - (PBP_PAGE_SIZE_256 << PBP_PAGE_SIZE_TX_SHIFT); - else - val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | - (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); + val8 = (priv->fops->pbp_rx << PBP_PAGE_SIZE_RX_SHIFT) | + (priv->fops->pbp_tx << PBP_PAGE_SIZE_TX_SHIFT); if (priv->rtl_chip != RTL8192E) rtl8xxxu_write8(priv, REG_PBP, val8); @@ -9728,6 +9725,8 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, .trxff_boundary = 0x27ff, + .pbp_rx = PBP_PAGE_SIZE_128, + .pbp_tx = PBP_PAGE_SIZE_128, .mactable = rtl8723a_mac_init_table, }; @@ -9761,6 +9760,8 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .adda_2t_path_on_a = 0x01c00014, .adda_2t_path_on_b = 0x01c00014, .trxff_boundary = 0x3f7f, + .pbp_rx = PBP_PAGE_SIZE_256, + .pbp_tx = PBP_PAGE_SIZE_256, .mactable = rtl8723b_mac_init_table, }; @@ -9792,6 +9793,8 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .adda_2t_path_on_a = 0x04db25a4, .adda_2t_path_on_b = 0x0b1b25a4, .trxff_boundary = 0x27ff, + .pbp_rx = PBP_PAGE_SIZE_128, + .pbp_tx = PBP_PAGE_SIZE_128, .mactable = rtl8723a_mac_init_table, }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index b87cd2bef53c..8064b264ad0b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1310,6 +1310,8 @@ struct rtl8xxxu_fileops { u32 adda_2t_path_on_a; u32 adda_2t_path_on_b; u16 trxff_boundary; + u8 pbp_rx; + u8 pbp_tx; struct rtl8xxxu_reg8val *mactable; u8 total_page_num; u8 page_num_hi; From 747bf237592cd7237e52692772a3fe3abeca0872 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:04 -0400 Subject: [PATCH 072/164] rtl8xxxu: Split USB quirks into gen1 and gen2 quirks This removes a bunch of if () spaghetti and re-applies the USB bus quirks for 8188/8192 that had gotten lost. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 95 +++++++++++-------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3e3ca28d5709..821be8725256 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6899,6 +6899,50 @@ static int rtl8xxxu_flush_fifo(struct rtl8xxxu_priv *priv) return retval; } +static void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv) +{ + /* Fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + /* + * This sets TXDMA_OFFSET_DROP_DATA_EN (bit 9) as well as bits + * 8 and 5, for which I have found no documentation. + */ + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* + * Solve too many protocol error on USB bus. + * Can't do this for 8188/8192 UMC A cut parts + */ + if (!(!priv->chip_cut && priv->vendor_umc)) { + rtl8xxxu_write8(priv, 0xfe40, 0xe6); + rtl8xxxu_write8(priv, 0xfe41, 0x94); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x19); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe5); + rtl8xxxu_write8(priv, 0xfe41, 0x91); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe2); + rtl8xxxu_write8(priv, 0xfe41, 0x81); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + } +} + +static void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); + val32 |= TXDMA_OFFSET_DROP_DATA_EN; + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); +} + static int rtl8723au_power_on(struct rtl8xxxu_priv *priv) { u8 val8; @@ -7563,29 +7607,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - /* Solve too many protocol error on USB bus */ - /* Can't do this for 8188/8192 UMC A cut parts */ - if (priv->rtl_chip == RTL8723A || - ((priv->rtl_chip == RTL8192C || priv->rtl_chip == RTL8191C || - priv->rtl_chip == RTL8188C) && - (priv->chip_cut || !priv->vendor_umc))) { - rtl8xxxu_write8(priv, 0xfe40, 0xe6); - rtl8xxxu_write8(priv, 0xfe41, 0x94); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x19); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe5); - rtl8xxxu_write8(priv, 0xfe41, 0x91); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - - rtl8xxxu_write8(priv, 0xfe40, 0xe2); - rtl8xxxu_write8(priv, 0xfe41, 0x81); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - } - if (priv->fops->phy_init_antenna_selection) priv->fops->phy_init_antenna_selection(priv); @@ -7604,6 +7625,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) case RTL8723A: rftable = rtl8723au_radioa_1t_init_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); break; case RTL8723B: rftable = rtl8723bu_radioa_1t_init_table; @@ -7706,23 +7733,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Chip specific quirks */ - if (priv->rtl_chip == RTL8723A) { - /* Fix USB interface interference issue */ - rtl8xxxu_write8(priv, 0xfe40, 0xe0); - rtl8xxxu_write8(priv, 0xfe41, 0x8d); - rtl8xxxu_write8(priv, 0xfe42, 0x80); - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - } else { - val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK); - val32 |= TXDMA_OFFSET_DROP_DATA_EN; - rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); - } + priv->fops->usb_quirks(priv); /* * Presumably this is for 8188EU as well @@ -9712,6 +9723,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, + .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, .report_connect = rtl8723au_report_connect, @@ -9746,6 +9758,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, + .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, @@ -9780,6 +9793,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8723a_disable_rf, + .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, .report_connect = rtl8723au_report_connect, @@ -9813,6 +9827,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8723b_disable_rf, + .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8723bu_update_rate_mask, .report_connect = rtl8723bu_report_connect, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 8064b264ad0b..da86f3f528b4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1293,6 +1293,7 @@ struct rtl8xxxu_fileops { void (*init_statistics) (struct rtl8xxxu_priv *priv); void (*enable_rf) (struct rtl8xxxu_priv *priv); void (*disable_rf) (struct rtl8xxxu_priv *priv); + void (*usb_quirks) (struct rtl8xxxu_priv *priv); void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel, bool ht40); void (*update_rate_mask) (struct rtl8xxxu_priv *priv, From 31133da702e4229acbd813350660f3053daa57c6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:05 -0400 Subject: [PATCH 073/164] rtl8xxxu: Remove unneeded 8192eu hack This removes an unneeded hack for 8192eu, and allows for initializing REG_FPGA0_XAB_RF_SW_CTRL at the same point as it is done for all other parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 821be8725256..5c56a4fc088b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7680,15 +7680,12 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* RFSW Control - clear bit 14 ?? */ if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); - /* 0x07000760 */ - if (priv->rtl_chip == RTL8192E) { - val32 = 0; - } else { - val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - } + + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E) From 46b378318de9e8e9d3b479e6adb2cec55c01c2ef Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:06 -0400 Subject: [PATCH 074/164] rtl8xxxu: 8192eu Fix bug in LDPC RX hang fix Write the adjusted value back to the correct register Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5c56a4fc088b..6febda5d0c75 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7967,7 +7967,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_8192E_LDOV12_CTRL, 0x75); val32 &= 0xfff00fff; val32 |= 0x0007e000; - rtl8xxxu_write32(priv, REG_8192E_LDOV12_CTRL, val32); + rtl8xxxu_write32(priv, REG_AFE_MISC, val32); } exit: return ret; From a39b683966559902dab4ea7d24b3223102d6971f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 14:59:07 -0400 Subject: [PATCH 075/164] Re-enable 8192eu support Revert "rtl8xxxu: Temporarily disable 8192eu device init" This reverts commit ccfe1e85322090649d2fae599e55300c1512bf15. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6febda5d0c75..39a033c02871 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3137,10 +3137,6 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) raw[i + 6], raw[i + 7]); } } - /* - * Temporarily disable 8192eu support - */ - return -EINVAL; return 0; } From e1d70c9b04000ee122c450627ed0614c676339a5 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:06 -0400 Subject: [PATCH 076/164] rtl8xxxu: Mark 0x050d:0x1004 as tested This dongle was tested successfully by Andrea Merello Reported-by: Andrea Merello Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 39a033c02871..037b64f7bea4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -9560,6 +9560,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (id->idProduct == 0x7811) untested = 0; break; + case 0x050d: + if (id->idProduct == 0x1004) + untested = 0; + break; default: break; } @@ -9864,6 +9868,9 @@ static struct usb_device_id dev_table[] = { /* Tested by Larry Finger */ {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Tested by Andrea Merello */ +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, /* Currently untested 8188 series devices */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, @@ -9948,8 +9955,6 @@ static struct usb_device_id dev_table[] = { /* Currently untested 8192 series devices */ {USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, -{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), - .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff), From 37ba4b6265ea0aa6c3369e4cf736ecbac31c40c9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Apr 2016 16:37:07 -0400 Subject: [PATCH 077/164] rtl8xxxu: fix uninitialized return value in ret several functions are not initializing a return status in ret resulting in garbage to be returned instead of 0 for success. Currently, the calls to these functions are not checking the return, however, it seems prudent to return the correct status in case they are to be checked at a later date. Signed-off-by: Colin Ian King Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 037b64f7bea4..b88cf1631489 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6370,7 +6370,7 @@ static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) { u8 val8; - int count, ret; + int count, ret = 0; /* Start of rtl8723AU_card_enable_flow */ /* Act to Cardemu sequence*/ @@ -6420,7 +6420,7 @@ static int rtl8723bu_active_to_emu(struct rtl8xxxu_priv *priv) u8 val8; u16 val16; u32 val32; - int count, ret; + int count, ret = 0; /* Turn off RF */ rtl8xxxu_write8(priv, REG_RF_CTRL, 0); @@ -6477,7 +6477,7 @@ static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) { u8 val8; u8 val32; - int count, ret; + int count, ret = 0; rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); From 4062b8ffec36df80d808d3bc3352e0f9c9abd3de Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:08 -0400 Subject: [PATCH 078/164] rtl8xxxu: Move PHY RF init into device specific functions Load the RF table in init_phy_rf(), which allows for applying device specific RF hacks in the same place. Getting rid of more ugly if () clutter. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 133 +++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index b88cf1631489..50ca3eb875bd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4015,6 +4015,80 @@ static int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv, return 0; } +static int rtl8723au_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8723au_radioa_1t_init_table, RF_A); + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + + return ret; +} + +static int rtl8723bu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8723bu_radioa_1t_init_table, RF_A); + /* + * PHY LCK + */ + rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdfbe0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, 0x8c01); + msleep(200); + rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdffe0); + + return ret; +} + +#ifdef CONFIG_RTL8XXXU_UNTESTED +static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_rfregval *rftable; + int ret; + + if (priv->rtl_chip == RTL8188C) { + if (priv->hi_pa) + rftable = rtl8188ru_radioa_1t_highpa_table; + else + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + } else if (priv->rf_paths == 1) { + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + } else { + rftable = rtl8192cu_radioa_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + goto exit; + rftable = rtl8192cu_radiob_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + } + +exit: + return ret; +} +#endif + +static int rtl8192eu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radioa_init_table, RF_A); + if (ret) + goto exit; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radiob_init_table, RF_B); + +exit: + return ret; +} + static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data) { int ret = -EBUSY; @@ -7552,7 +7626,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; - struct rtl8xxxu_rfregval *rftable; bool macpower; int ret; u8 val8; @@ -7617,59 +7690,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; - switch(priv->rtl_chip) { - case RTL8723A: - rftable = rtl8723au_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - - /* Reduce 80M spur */ - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); - break; - case RTL8723B: - rftable = rtl8723bu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - /* - * PHY LCK - */ - rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdfbe0); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, 0x8c01); - msleep(200); - rtl8xxxu_write_rfreg(priv, RF_A, 0xb0, 0xdffe0); - break; - case RTL8188C: - if (priv->hi_pa) - rftable = rtl8188ru_radioa_1t_highpa_table; - else - rftable = rtl8192cu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - break; - case RTL8191C: - rftable = rtl8192cu_radioa_1t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - break; - case RTL8192C: - rftable = rtl8192cu_radioa_2t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - if (ret) - break; - rftable = rtl8192cu_radiob_2t_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); - break; - case RTL8192E: - rftable = rtl8192eu_radioa_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); - if (ret) - break; - rftable = rtl8192eu_radiob_init_table; - ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); - break; - default: - ret = -EINVAL; - } - + ret = priv->fops->init_phy_rf(priv); if (ret) goto exit; @@ -9715,6 +9736,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9747,6 +9769,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .reset_8051 = rtl8723bu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, .init_phy_bb = rtl8723bu_init_phy_bb, + .init_phy_rf = rtl8723bu_init_phy_rf, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, @@ -9785,6 +9808,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, @@ -9819,6 +9843,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_auto_llt_table, .init_phy_bb = rtl8192eu_init_phy_bb, + .init_phy_rf = rtl8192eu_init_phy_rf, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index da86f3f528b4..3efbb6042ca2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1284,6 +1284,7 @@ struct rtl8xxxu_fileops { void (*reset_8051) (struct rtl8xxxu_priv *priv); int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page); void (*init_phy_bb) (struct rtl8xxxu_priv *priv); + int (*init_phy_rf) (struct rtl8xxxu_priv *priv); void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv); void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv); void (*config_channel) (struct ieee80211_hw *hw); From b591e982bc44baf79f6ebb963eb47fe5e223e8e7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:09 -0400 Subject: [PATCH 079/164] rtl8xxxu: For devices with external PA (8188RU), limit CCK TX power Per the vendor driver, devices with an external PA needs limiting it's TX power to 0x20. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 50ca3eb875bd..578d1bf2c821 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2421,6 +2421,13 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) cck[0] = priv->cck_tx_power_index_A[group]; cck[1] = priv->cck_tx_power_index_B[group]; + if (priv->hi_pa) { + if (cck[0] > 0x20) + cck[0] = 0x20; + if (cck[1] > 0x20) + cck[1] = 0x20; + } + ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; From 78a8421959af5e13dd96493e3b74d8d7c7406609 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:10 -0400 Subject: [PATCH 080/164] rtl8xxxu: Apply 8188RU workaround for UMC B cut parts correctly This patch was being missed since rtl_chip will never match RTL8188C if hi_pa is true. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 578d1bf2c821..bebe484c1dd6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3756,7 +3756,7 @@ static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) else rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); - if (priv->rtl_chip == RTL8188C && priv->hi_pa && + if (priv->rtl_chip == RTL8188R && priv->hi_pa && priv->vendor_umc && priv->chip_cut == 1) rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); From 8d95c8084f5621240006f730986a3346b7794863 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:11 -0400 Subject: [PATCH 081/164] rtl8xxxu: Use rtl_chip == RTL8188R to identify high PA parts This is simpler than checking for RTL8188C && hi_pa. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bebe484c1dd6..8bf9a74bec63 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3054,6 +3054,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) if (efuse->rf_regulatory & 0x20) { sprintf(priv->chip_name, "8188RU"); + priv->rtl_chip = RTL8188R; priv->hi_pa = 1; } @@ -4059,11 +4060,8 @@ static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv) struct rtl8xxxu_rfregval *rftable; int ret; - if (priv->rtl_chip == RTL8188C) { - if (priv->hi_pa) - rftable = rtl8188ru_radioa_1t_highpa_table; - else - rftable = rtl8192cu_radioa_1t_init_table; + if (priv->rtl_chip == RTL8188R) { + rftable = rtl8188ru_radioa_1t_highpa_table; ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); } else if (priv->rf_paths == 1) { rftable = rtl8192cu_radioa_1t_init_table; @@ -7219,7 +7217,7 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtl_chip == RTL8188C && priv->hi_pa) { + if (priv->rtl_chip == RTL8188R) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 &= ~BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); @@ -7323,7 +7321,7 @@ static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) /* * Workaround for 8188RU LNA power leakage problem. */ - if (priv->rtl_chip == RTL8188C && priv->hi_pa) { + if (priv->rtl_chip == RTL8188R) { val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); val32 |= BIT(1); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); From 8e25496090431553ce2200f53bbe194b9e0a19d2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:12 -0400 Subject: [PATCH 082/164] rtl8xxxu: Match 8723bu power down sequence to vendor driver In particular set APS_FSMCO_WLON_RESET in the right register, and do not overwrite too much of REG_CR. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 8bf9a74bec63..5685fd744fbc 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6510,9 +6510,9 @@ static int rtl8723bu_active_to_emu(struct rtl8xxxu_priv *priv) rtl8xxxu_write16(priv, REG_GPIO_INTM, val16); /* Release WLON reset 0x04[16]= 1*/ - val32 = rtl8xxxu_read32(priv, REG_GPIO_INTM); + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); val32 |= APS_FSMCO_WLON_RESET; - rtl8xxxu_write32(priv, REG_GPIO_INTM, val32); + rtl8xxxu_write32(priv, REG_APS_FSMCO, val32); /* 0x0005[1] = 1 turn off MAC by HW state machine*/ val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); @@ -7376,7 +7376,7 @@ static void rtl8723bu_power_off(struct rtl8xxxu_priv *priv) val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE; rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8); - rtl8xxxu_write16(priv, REG_CR, 0x0000); + rtl8xxxu_write8(priv, REG_CR, 0x0000); rtl8xxxu_active_to_lps(priv); @@ -7393,7 +7393,15 @@ static void rtl8723bu_power_off(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); rtl8723bu_active_to_emu(priv); - rtl8xxxu_emu_to_disabled(priv); + + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(3); /* APS_FSMCO_HW_SUSPEND */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); } #ifdef NEED_PS_TDMA From 8cae2f1da87c82b2a0031f4d19c142e7bc22f1d7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:13 -0400 Subject: [PATCH 083/164] rtl8xxxu: Unregister from mac80211 before shutting down the device This fixes a long standing bug where mac80211 would send disconnect packets to the device, after we had shut down the device. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 5685fd744fbc..2b71a2baaf9b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8003,13 +8003,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) return ret; } -static void rtl8xxxu_disable_device(struct ieee80211_hw *hw) -{ - struct rtl8xxxu_priv *priv = hw->priv; - - priv->fops->power_off(priv); -} - static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, struct ieee80211_key_conf *key, const u8 *mac) { @@ -9726,13 +9719,14 @@ static void rtl8xxxu_disconnect(struct usb_interface *interface) hw = usb_get_intfdata(interface); priv = hw->priv; - rtl8xxxu_disable_device(hw); + ieee80211_unregister_hw(hw); + + priv->fops->power_off(priv); + usb_set_intfdata(interface, NULL); dev_info(&priv->udev->dev, "disconnecting\n"); - ieee80211_unregister_hw(hw); - kfree(priv->fw_data); mutex_destroy(&priv->usb_buf_mutex); mutex_destroy(&priv->h2c_mutex); From eb18806261da3de958b5569fb6d93ed0d773028b Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:14 -0400 Subject: [PATCH 084/164] rtl8xxxu: Update copyright statement to include 2016 Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2b71a2baaf9b..de62f0ba11d7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver * - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 3efbb6042ca2..a1b076cdab6f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index e7709a5bcb3a..b0e0c642302c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2015 Jes Sorensen + * Copyright (c) 2014 - 2016 Jes Sorensen * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as From b9f9d6992f8338e919c977e4e18473f57dcb874d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:15 -0400 Subject: [PATCH 085/164] rtl8xxxu: Set register 0xfe10 on rtl8192cu based parts This register is undocumented in the vendor code, but it is set unconditionally for all 8192cu/8188cu/8188ru parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index de62f0ba11d7..6280d3d0cec7 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7214,6 +7214,8 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE; rtl8xxxu_write16(priv, REG_CR, val16); + rtl8xxxu_write8(priv, 0xfe10, 0x19); + /* * Workaround for 8188RU LNA power leakage problem. */ From 2fc0b8e5a17dc415508d918eeeb1aa47443ae642 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:16 -0400 Subject: [PATCH 086/164] rtl8xxxu: Add TX power base values for gen1 parts Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 118 +++++++++++++++--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 26 ++++ 2 files changed, 130 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6280d3d0cec7..422e7fa6756d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -214,6 +214,72 @@ static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { {0xffff, 0xff}, }; +static struct rtl8xxxu_power_base rtl8188r_power_base = { + .reg_0e00 = 0x06080808, + .reg_0e04 = 0x00040406, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x04060608, + .reg_0e14 = 0x00020204, + .reg_0e18 = 0x04060608, + .reg_0e1c = 0x00020204, + + .reg_0830 = 0x06080808, + .reg_0834 = 0x00040406, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x04060608, + .reg_0848 = 0x00020204, + .reg_084c = 0x04060608, + .reg_0868 = 0x00020204, +}; + +static struct rtl8xxxu_power_base rtl8192c_power_base = { + .reg_0e00 = 0x07090c0c, + .reg_0e04 = 0x01020405, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x0b0c0c0e, + .reg_0e14 = 0x01030506, + .reg_0e18 = 0x0b0c0d0e, + .reg_0e1c = 0x01030509, + + .reg_0830 = 0x07090c0c, + .reg_0834 = 0x01020405, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x0b0c0d0e, + .reg_0848 = 0x01030509, + .reg_084c = 0x0b0c0d0e, + .reg_0868 = 0x01030509, +}; + +static struct rtl8xxxu_power_base rtl8723a_power_base = { + .reg_0e00 = 0x0a0c0c0c, + .reg_0e04 = 0x02040608, + .reg_0e08 = 0x00000000, + .reg_086c = 0x00000000, + + .reg_0e10 = 0x0a0c0d0e, + .reg_0e14 = 0x02040608, + .reg_0e18 = 0x0a0c0d0e, + .reg_0e1c = 0x02040608, + + .reg_0830 = 0x0a0c0c0c, + .reg_0834 = 0x02040608, + .reg_0838 = 0x00000000, + .reg_086c_2 = 0x00000000, + + .reg_083c = 0x0a0c0d0e, + .reg_0848 = 0x02040608, + .reg_084c = 0x0a0c0d0e, + .reg_0868 = 0x02040608, +}; + static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { {0x800, 0x80040000}, {0x804, 0x00000003}, {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, @@ -2410,6 +2476,7 @@ static void rtl8723bu_config_channel(struct ieee80211_hw *hw) static void rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) { + struct rtl8xxxu_power_base *power_base = priv->power_base; u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS]; u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b; @@ -2418,8 +2485,8 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) group = rtl8723a_channel_to_group(channel); - cck[0] = priv->cck_tx_power_index_A[group]; - cck[1] = priv->cck_tx_power_index_B[group]; + cck[0] = priv->cck_tx_power_index_A[group] - 1; + cck[1] = priv->cck_tx_power_index_B[group] - 1; if (priv->hi_pa) { if (cck[0] > 0x20) @@ -2430,6 +2497,10 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; + if (ofdm[0]) + ofdm[0] -= 1; + if (ofdm[1]) + ofdm[1] -= 1; ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a; ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b; @@ -2485,27 +2556,39 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) ofdmbase[0] << 16 | ofdmbase[0] << 24; ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 | ofdmbase[1] << 16 | ofdmbase[1] << 24; - rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm_b); - rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, + ofdm_a + power_base->reg_0e00); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, + ofdm_b + power_base->reg_0830); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, + ofdm_a + power_base->reg_0e04); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, + ofdm_b + power_base->reg_0834); mcs_a = mcsbase[0] | mcsbase[0] << 8 | mcsbase[0] << 16 | mcsbase[0] << 24; mcs_b = mcsbase[1] | mcsbase[1] << 8 | mcsbase[1] << 16 | mcsbase[1] << 24; - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, + mcs_a + power_base->reg_0e10); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, + mcs_b + power_base->reg_083c); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, + mcs_a + power_base->reg_0e14); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, + mcs_b + power_base->reg_0848); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs_a); - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, + mcs_a + power_base->reg_0e18); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, + mcs_b + power_base->reg_084c); - rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, + mcs_a + power_base->reg_0e1c); for (i = 0; i < 3; i++) { if (i != 2) val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0; @@ -2513,7 +2596,8 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0; rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8); } - rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs_b); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, + mcs_b + power_base->reg_0868); for (i = 0; i < 3; i++) { if (i != 2) val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0; @@ -2920,6 +3004,9 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; } + + priv->power_base = &rtl8723a_power_base; + dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); dev_info(&priv->udev->dev, "Product: %.41s\n", @@ -3052,10 +3139,13 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) dev_info(&priv->udev->dev, "Product: %.20s\n", efuse->device_name); + priv->power_base = &rtl8192c_power_base; + if (efuse->rf_regulatory & 0x20) { sprintf(priv->chip_name, "8188RU"); priv->rtl_chip = RTL8188R; priv->hi_pa = 1; + priv->power_base = &rtl8188r_power_base; } if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index a1b076cdab6f..ebd1a6e7b813 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -629,6 +629,31 @@ struct rtl8xxxu_firmware_header { u8 data[0]; }; +/* + * 8723au/8192cu/8188ru required base power index offset tables. + */ +struct rtl8xxxu_power_base { + u32 reg_0e00; + u32 reg_0e04; + u32 reg_0e08; + u32 reg_086c; + + u32 reg_0e10; + u32 reg_0e14; + u32 reg_0e18; + u32 reg_0e1c; + + u32 reg_0830; + u32 reg_0834; + u32 reg_0838; + u32 reg_086c_2; + + u32 reg_083c; + u32 reg_0848; + u32 reg_084c; + u32 reg_0868; +}; + /* * The 8723au has 3 channel groups: 1-3, 4-9, and 10-14 */ @@ -1201,6 +1226,7 @@ struct rtl8xxxu_priv { struct rtl8723au_idx ofdm_tx_power_diff[RTL8723B_TX_COUNT]; struct rtl8723au_idx ht20_tx_power_diff[RTL8723B_TX_COUNT]; struct rtl8723au_idx ht40_tx_power_diff[RTL8723B_TX_COUNT]; + struct rtl8xxxu_power_base *power_base; u32 chip_cut:4; u32 rom_rev:4; u32 is_multi_func:1; From cabb550e2b97b8ea42124a93d4665ca052f3e3ff Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:17 -0400 Subject: [PATCH 087/164] rtl8xxxu: Fix 8188RU support The 8188RU does not like PAPE to be enabled, while all the other gen1 parts seem to require it. This makes the RTL8188RU able to associate for me. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 21 ++++++++++++------- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 422e7fa6756d..cf7832bfdde8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3145,6 +3145,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) sprintf(priv->chip_name, "8188RU"); priv->rtl_chip = RTL8188R; priv->hi_pa = 1; + priv->no_pape = 1; priv->power_base = &rtl8188r_power_base; } @@ -5555,9 +5556,12 @@ static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); - val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); - val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); - rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + if (!priv->no_pape) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | + (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + } val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); val32 &= ~BIT(10); @@ -7804,11 +7808,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | - FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | - ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << - FPGA0_RF_BD_CTRL_SHIFT); - + FPGA0_RF_ANTSWB | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB) << FPGA0_RF_BD_CTRL_SHIFT); + if (!priv->no_pape) { + val32 |= (FPGA0_RF_PAPE | + (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + } rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index ebd1a6e7b813..3e2643c79b56 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1287,6 +1287,7 @@ struct rtl8xxxu_priv { u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; enum rtl8xxxu_rtl_chip rtl_chip; u8 pi_enabled:1; + u8 no_pape:1; u8 int_buf[USB_INTR_CONTENT_LENGTH]; }; From 6a62f9d5273dbc8ec776717a73a8a223b9e5f38e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:18 -0400 Subject: [PATCH 088/164] rtl8xxxu: Fix OOPS if user tries to add device via /sys This driver relies on driver_info in struct usb_device_id, so allowing adding a device via /sys/bus/usb/drivers/rtl8xxxu/new_id will cause a NULL pointer dereference. Set .no_dynamic_id = 1 to disable hot add of USB IDs. Reported-by: Xose Vazquez Perez Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index cf7832bfdde8..2d92e643fcd6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -10141,6 +10141,7 @@ static struct usb_driver rtl8xxxu_driver = { .probe = rtl8xxxu_probe, .disconnect = rtl8xxxu_disconnect, .id_table = dev_table, + .no_dynamic_id = 1, .disable_hub_initiated_lpm = 1, }; From ae5c01fd2fd816486169787440bf900d1b703230 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:19 -0400 Subject: [PATCH 089/164] rtl8xxxu: Implement rtl8192e_enable_rf() This implements an 8192eu specific enable_rf() function. The 8192eu is not a combo device, so no need for doing the BT specific bits needed by the 8723bu. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 2d92e643fcd6..a86b5c40efe4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7517,6 +7517,43 @@ static void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, } #endif +static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG); + val8 |= BIT(5); + rtl8xxxu_write8(priv, REG_GPIO_MUXCFG, val8); + + /* + * WLAN action by PTA + */ + rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x04); + + val32 = rtl8xxxu_read32(priv, REG_PWR_DATA); + val32 |= PWR_DATA_EEPRPAD_RFE_CTRL_EN; + rtl8xxxu_write32(priv, REG_PWR_DATA, val32); + + val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER); + val32 |= (BIT(0) | BIT(1)); + rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32); + + rtl8xxxu_write8(priv, REG_RFE_CTRL_ANTA_SRC, 0x77); + + val32 = rtl8xxxu_read32(priv, REG_LEDCFG0); + val32 &= ~BIT(24); + val32 |= BIT(23); + rtl8xxxu_write32(priv, REG_LEDCFG0, val32); + + /* + * Fix external switch Main->S1, Aux->S0 + */ + val8 = rtl8xxxu_read8(priv, REG_PAD_CTRL1); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8); +} + static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) { struct h2c_cmd h2c; @@ -9953,7 +9990,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, .config_channel = rtl8723bu_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, - .enable_rf = rtl8723b_enable_rf, + .enable_rf = rtl8192e_enable_rf, .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, From 265697eb2f1b6c472c4b09ff7e008bc8ab145b4f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:20 -0400 Subject: [PATCH 090/164] rtl8xxxu: Pause TX before calling disable_rf() All the disable_rf() functions were setting REG_TXPAUSE to 0xff to stop transmission. Do it centrally before calling disable_rf() instead. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a86b5c40efe4..928ca56f751c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2125,8 +2125,6 @@ static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) u8 sps0; u32 val32; - rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); - sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); /* RF RX code for preamble power saving */ @@ -7665,8 +7663,6 @@ static void rtl8723b_disable_rf(struct rtl8xxxu_priv *priv) { u32 val32; - rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); - val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA); val32 &= ~(BIT(22) | BIT(23)); rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val32); @@ -9591,6 +9587,8 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw) if (priv->usb_interrupts) usb_kill_anchored_urbs(&priv->int_anchor); + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + priv->fops->disable_rf(priv); /* From 171a900c4eb7b34667e64ffed316a50425b45581 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 14 Apr 2016 16:37:21 -0400 Subject: [PATCH 091/164] rtl8xxxu: MAINTAINERS: Update to point to the active devel branch Update the MAINTAINERS info to reflect active development of the rtl8xxxu driver. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4851f02281d6..6ac970ba54b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9490,7 +9490,7 @@ F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/ RTL8XXXU WIRELESS DRIVER (rtl8xxxu) M: Jes Sorensen L: linux-wireless@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8723au-mac80211 +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel S: Maintained F: drivers/net/wireless/realtek/rtl8xxxu/ From 87be054a30de1d48a4c9850543080b8cc9854d2c Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 5 Apr 2016 20:58:26 +0530 Subject: [PATCH 092/164] ath10k: fix return value for btcoex and peer stats debugfs Return value is incorrect for btcoex and peer stats debugfs 'write' entries if the user provides a value that matches with the already available debugfs entry, this results in the debugfs entry getting stuck and the operation has to be terminated manually. Fix this by returning the appropriate return 'count' as we do it for other debugfs entries like pktlog etc. Fixes: cc61a1bbbc0e ("ath10k: enable debugfs provision to enable Peer Stats feature") Fixes: c28e6f06ff40 ("ath10k: fix sanity check on enabling btcoex via debugfs") Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 76bbe17b25b6..e7d441caa288 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -2122,7 +2122,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, struct ath10k *ar = file->private_data; char buf[32]; size_t buf_size; - int ret = 0; + int ret; bool val; buf_size = min(count, (sizeof(buf) - 1)); @@ -2142,8 +2142,10 @@ static ssize_t ath10k_write_btcoex(struct file *file, goto exit; } - if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) + if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) { + ret = count; goto exit; + } if (val) set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags); @@ -2189,7 +2191,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file, struct ath10k *ar = file->private_data; char buf[32]; size_t buf_size; - int ret = 0; + int ret; bool val; buf_size = min(count, (sizeof(buf) - 1)); @@ -2209,8 +2211,10 @@ static ssize_t ath10k_write_peer_stats(struct file *file, goto exit; } - if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) + if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) { + ret = count; goto exit; + } if (val) set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags); From 1ce8c1484e80010a6e4b9611c65668ff77556f45 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 7 Apr 2016 12:11:54 +0530 Subject: [PATCH 093/164] ath10k: fix rx_channel during hw reconfigure Upon firmware assert, restart work will be triggered so that mac80211 will reconfigure the driver. An issue is reported that after restart work, survey dump data do not contain in-use (SURVEY_INFO_IN_USE) info for operating channel. During reconfigure, since mac80211 already has valid channel context for given radio, channel context iteration return num_chanctx > 0. Hence rx_channel is always NULL. Fix this by assigning channel context to rx_channel when driver restart is in progress. Cc: stable@vger.kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d9d98bf22b3e..32e9d5010b4e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6893,7 +6893,13 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, def = &vifs[0].new_ctx->def; ar->rx_channel = def->chan; - } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) { + } else if ((ctx && ath10k_mac_num_chanctxs(ar) == 0) || + (ctx && (ar->state == ATH10K_STATE_RESTARTED))) { + /* During driver restart due to firmware assert, since mac80211 + * already has valid channel context for given radio, channel + * context iteration return num_chanctx > 0. So fix rx_channel + * when restart is in progress. + */ ar->rx_channel = ctx->def.chan; } else { ar->rx_channel = NULL; From de72a20dc3714918b208430dd426c9f6a23ffaec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 11 Apr 2016 11:15:20 +0300 Subject: [PATCH 094/164] ath10k: add some sanity checks to peer_map_event() functions Smatch complains that since "ev->peer_id" comes from skb->data that means we can't trust it and have to do a bounds check on it to prevent an array overflow. Fixes: 6942726f7f7b ('ath10k: add fast peer_map lookup') Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/txrx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 8c7086989a71..576e7c42ed65 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -190,6 +190,13 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer map event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr); if (!peer) { @@ -218,6 +225,13 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer unmap event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find_by_id(ar, ev->peer_id); if (!peer) { From 7e247a9e88dc811d0b7b6a70af1d741054772bc4 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Tue, 12 Apr 2016 20:15:53 +0530 Subject: [PATCH 095/164] ath10k: add dynamic tx mode switch config support for qca4019 push-pull mode needs certain amount the host driver involvement for managing queues in the host memory and packet delivery to firmware. qca4019 wifi firmware has an option to stay in push mode for less number of active traffic flow and then switch to push-pull mode when the active traffic flow goes beyond the certain limit. The advantage of staying in push mode for less active traffic is, the host cpu consumption is reduced. qca4019 firmware supports this flexibility of the mode switch. It takes the host driver interest (LOW_PERF/HIGH_PERF) via WMI_EXT_RESOURCE_CFG_CMDID, LOW_PERF - fw would stay in push mode and switch to push-pull based on demand. HIGH_PERF - fw would stay in push-pull mode from the boot. To make this configuration generic, new WMI services WMI_SERVICE_TX_MODE_PUSH_ONLY, WMI_SERVICE_TX_MODE_PUSH_PULL, WMI_SERVICE_TX_MODE_DYNAMIC are introduced to take dynamic tx mode switch support availability in firmware. Based on WMI_SERVICE_TX_MODE_DYNAMIC, LOW_PERF or HIGHT_PERF is configured to the firmware. Signed-off-by: Raja Mani Signed-off-by: Tamizh chelvam Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 +-- drivers/net/wireless/ath/ath10k/mac.c | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.h | 1 + drivers/net/wireless/ath/ath10k/wmi.h | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b2c7fe3d30a4..1c4106b84a35 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1787,8 +1787,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) if (ath10k_peer_stats_enabled(ar)) val = WMI_10_4_PEER_STATS; - status = ath10k_wmi_ext_resource_config(ar, - WMI_HOST_PLATFORM_HIGH_PERF, val); + status = ath10k_mac_ext_resource_config(ar, val); if (status) { ath10k_err(ar, "failed to send ext resource cfg command : %d\n", diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 32e9d5010b4e..fb393596f236 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -157,6 +157,26 @@ ath10k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) return 1; } +int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val) +{ + enum wmi_host_platform_type platform_type; + int ret; + + if (test_bit(WMI_SERVICE_TX_MODE_DYNAMIC, ar->wmi.svc_map)) + platform_type = WMI_HOST_PLATFORM_LOW_PERF; + else + platform_type = WMI_HOST_PLATFORM_HIGH_PERF; + + ret = ath10k_wmi_ext_resource_config(ar, platform_type, val); + + if (ret && ret != -EOPNOTSUPP) { + ath10k_warn(ar, "failed to configure ext resource: %d\n", ret); + return ret; + } + + return 0; +} + /**********/ /* Crypto */ /**********/ diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 2c3327beb445..1bd29ecfcdcc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -81,6 +81,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, u16 peer_id, u8 tid); +int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 378f2998cd5a..db2553522d8b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -180,6 +180,9 @@ enum wmi_service { WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, WMI_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_SERVICE_TX_MODE_PUSH_ONLY, + WMI_SERVICE_TX_MODE_PUSH_PULL, + WMI_SERVICE_TX_MODE_DYNAMIC, /* keep last */ WMI_SERVICE_MAX, @@ -302,6 +305,9 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, WMI_10_4_SERVICE_PEER_STATS, WMI_10_4_SERVICE_MESH_11S, + WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY, + WMI_10_4_SERVICE_TX_MODE_PUSH_PULL, + WMI_10_4_SERVICE_TX_MODE_DYNAMIC, }; static inline char *wmi_service_name(int service_id) @@ -396,6 +402,9 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT); + SVCSTR(WMI_SERVICE_TX_MODE_PUSH_ONLY); + SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL); + SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC); default: return NULL; } @@ -643,6 +652,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_PEER_STATS, len); SVCMAP(WMI_10_4_SERVICE_MESH_11S, WMI_SERVICE_MESH_11S, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY, + WMI_SERVICE_TX_MODE_PUSH_ONLY, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_PULL, + WMI_SERVICE_TX_MODE_PUSH_PULL, len); + SVCMAP(WMI_10_4_SERVICE_TX_MODE_DYNAMIC, + WMI_SERVICE_TX_MODE_DYNAMIC, len); } #undef SVCMAP From f286dd899b4f1445279af6b5965c335ae6f998f7 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 1 Jan 2016 19:09:32 +0100 Subject: [PATCH 096/164] ath9k_htc: Replace a variable initialisation by an assignment in ath9k_htc_set_channel() Replace an explicit initialisation for one local variable at the beginning by a conditional assignment. Signed-off-by: Markus Elfring Reviewed-by: Oleksij Rempel Reviewed-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 639294a9e34d..6c5047cc837e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -246,7 +246,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ieee80211_conf *conf = &common->hw->conf; bool fastcc; struct ieee80211_channel *channel = hw->conf.chandef.chan; - struct ath9k_hw_cal_data *caldata = NULL; + struct ath9k_hw_cal_data *caldata; enum htc_phymode mode; __be16 htc_mode; u8 cmd_rsp; @@ -274,10 +274,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, priv->ah->curchan->channel, channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), fastcc); - - if (!fastcc) - caldata = &priv->caldata; - + caldata = fastcc ? NULL : &priv->caldata; ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { ath_err(common, From 71f5137bf010c6faffab50c0ec15374c59c4a411 Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Fri, 1 Apr 2016 11:37:08 +0200 Subject: [PATCH 097/164] ath9k: interpret requested txpower in EIRP domain Tx power limitations at upper layers are interpreted in the EIRP domain. When the user requests a given maximum txpower, e.g. with: 'iw phy0 set txpower fixed 1500', he expects the EIRP to be at or below 15dBm. In ath9k_hw_apply_txpower(), the interpretation is different: the antenna-gain is capped against the current txpower limit in the regulatory, but not against the user set value. It ensures that the resulting EIRP is below the limit defined by the active countrycode, but not below the value the user requested. In a scenario like e.g. a) antenna_gain=6 b) countrycode limits to eirp=18 c) user set txpower=15 this will cause a setting for AR_PHY_POWER_TX_RATE regs resulting in an EIRP > 15. This patch ensures that antenna-gain is considered whenever the txpower limit is adjusted and with that the user set limits are kept. Signed-off-by: Zefir Kurtisi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 42009065e234..8b2895f9ac7a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2914,8 +2914,7 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, { struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ieee80211_channel *channel; - int chan_pwr, new_pwr, max_gain; - int ant_gain, ant_reduction = 0; + int chan_pwr, new_pwr; if (!chan) return; @@ -2923,15 +2922,10 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, channel = chan->chan; chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); new_pwr = min_t(int, chan_pwr, reg->power_limit); - max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; - - ant_gain = get_antenna_gain(ah, chan); - if (ant_gain > max_gain) - ant_reduction = ant_gain - max_gain; ah->eep_ops->set_txpower(ah, chan, ath9k_regd_get_ctl(reg, chan), - ant_reduction, new_pwr, test); + get_antenna_gain(ah, chan), new_pwr, test); } void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) From 47f58b1ebe3739dad1ddeb5cd1f1e718648b4d24 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 10 Apr 2016 12:25:31 +0100 Subject: [PATCH 098/164] ath9k: remove duplicate assignment of variable ah ah is written twice with the same value, remove one of the redundant assignments to ah. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 77ace8d72d54..fb702c48a233 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -477,7 +477,7 @@ static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, static int ath9k_eeprom_request(struct ath_softc *sc, const char *name) { struct ath9k_eeprom_ctx ec; - struct ath_hw *ah = ah = sc->sc_ah; + struct ath_hw *ah = sc->sc_ah; int err; /* try to load the EEPROM content asynchronously */ From 3fb55c79d092d085bddd4fc94f250acfc1275f3d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:44:36 +0300 Subject: [PATCH 099/164] ath10k: remove deprecated firmware API 1 support This has ben deprecated years ago, I haven't heard anyone using it since and most likely it won't even work anymore. So just remove all of it. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 73 -------------------------- drivers/net/wireless/ath/ath10k/core.h | 3 -- drivers/net/wireless/ath/ath10k/hw.h | 12 ----- drivers/net/wireless/ath/ath10k/pci.c | 1 - drivers/net/wireless/ath/ath10k/wmi.c | 4 -- 5 files changed, 93 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1c4106b84a35..48389e0b87f6 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -63,8 +63,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, - .fw = QCA988X_HW_2_0_FW_FILE, - .otp = QCA988X_HW_2_0_OTP_FILE, .board = QCA988X_HW_2_0_BOARD_DATA_FILE, .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, @@ -82,8 +80,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, - .fw = QCA6174_HW_2_1_FW_FILE, - .otp = QCA6174_HW_2_1_OTP_FILE, .board = QCA6174_HW_2_1_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -102,8 +98,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, - .fw = QCA6174_HW_2_1_FW_FILE, - .otp = QCA6174_HW_2_1_OTP_FILE, .board = QCA6174_HW_2_1_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -122,8 +116,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, - .fw = QCA6174_HW_3_0_FW_FILE, - .otp = QCA6174_HW_3_0_OTP_FILE, .board = QCA6174_HW_3_0_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -143,8 +135,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, - .fw = QCA6174_HW_3_0_FW_FILE, - .otp = QCA6174_HW_3_0_OTP_FILE, .board = QCA6174_HW_3_0_BOARD_DATA_FILE, .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, @@ -167,8 +157,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 12064, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, - .fw = QCA99X0_HW_2_0_FW_FILE, - .otp = QCA99X0_HW_2_0_OTP_FILE, .board = QCA99X0_HW_2_0_BOARD_DATA_FILE, .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, @@ -186,8 +174,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, - .fw = QCA9377_HW_1_0_FW_FILE, - .otp = QCA9377_HW_1_0_OTP_FILE, .board = QCA9377_HW_1_0_BOARD_DATA_FILE, .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, @@ -205,8 +191,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 8124, .fw = { .dir = QCA9377_HW_1_0_FW_DIR, - .fw = QCA9377_HW_1_0_FW_FILE, - .otp = QCA9377_HW_1_0_OTP_FILE, .board = QCA9377_HW_1_0_BOARD_DATA_FILE, .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, @@ -229,8 +213,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cal_data_len = 12064, .fw = { .dir = QCA4019_HW_1_0_FW_DIR, - .fw = QCA4019_HW_1_0_FW_FILE, - .otp = QCA4019_HW_1_0_OTP_FILE, .board = QCA4019_HW_1_0_BOARD_DATA_FILE, .board_size = QCA4019_BOARD_DATA_SZ, .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, @@ -703,9 +685,6 @@ static void ath10k_core_free_board_files(struct ath10k *ar) static void ath10k_core_free_firmware_files(struct ath10k *ar) { - if (!IS_ERR(ar->otp)) - release_firmware(ar->otp); - if (!IS_ERR(ar->firmware)) release_firmware(ar->firmware); @@ -714,7 +693,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ath10k_swap_code_seg_release(ar); - ar->otp = NULL; ar->otp_data = NULL; ar->otp_len = 0; @@ -1000,50 +978,6 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) -{ - int ret = 0; - - if (ar->hw_params.fw.fw == NULL) { - ath10k_err(ar, "firmware file not defined\n"); - return -EINVAL; - } - - ar->firmware = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.fw); - if (IS_ERR(ar->firmware)) { - ret = PTR_ERR(ar->firmware); - ath10k_err(ar, "could not fetch firmware (%d)\n", ret); - goto err; - } - - ar->firmware_data = ar->firmware->data; - ar->firmware_len = ar->firmware->size; - - /* OTP may be undefined. If so, don't fetch it at all */ - if (ar->hw_params.fw.otp == NULL) - return 0; - - ar->otp = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.otp); - if (IS_ERR(ar->otp)) { - ret = PTR_ERR(ar->otp); - ath10k_err(ar, "could not fetch otp (%d)\n", ret); - goto err; - } - - ar->otp_data = ar->otp->data; - ar->otp_len = ar->otp->size; - - return 0; - -err: - ath10k_core_free_firmware_files(ar); - return ret; -} - static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) { size_t magic_len, len, ie_len; @@ -1253,13 +1187,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); - if (ret == 0) - goto success; - - ar->fw_api = 1; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - - ret = ath10k_core_fetch_firmware_api_1(ar); if (ret) return ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e6f889df1e0d..2d0cc92f3c5b 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -708,8 +708,6 @@ struct ath10k { struct ath10k_hw_params_fw { const char *dir; - const char *fw; - const char *otp; const char *board; size_t board_size; size_t board_ext_size; @@ -720,7 +718,6 @@ struct ath10k { const void *board_data; size_t board_len; - const struct firmware *otp; const void *otp_data; size_t otp_len; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index c0179bc4af29..aedd8987040b 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -35,8 +35,6 @@ #define QCA988X_HW_2_0_VERSION 0x4100016c #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 #define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0" -#define QCA988X_HW_2_0_FW_FILE "firmware.bin" -#define QCA988X_HW_2_0_OTP_FILE "otp.bin" #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 @@ -76,14 +74,10 @@ enum qca9377_chip_id_rev { }; #define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1" -#define QCA6174_HW_2_1_FW_FILE "firmware.bin" -#define QCA6174_HW_2_1_OTP_FILE "otp.bin" #define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234 #define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0" -#define QCA6174_HW_3_0_FW_FILE "firmware.bin" -#define QCA6174_HW_3_0_OTP_FILE "otp.bin" #define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234 @@ -94,23 +88,17 @@ enum qca9377_chip_id_rev { #define QCA99X0_HW_2_0_DEV_VERSION 0x01000000 #define QCA99X0_HW_2_0_CHIP_ID_REV 0x1 #define QCA99X0_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA99X0/hw2.0" -#define QCA99X0_HW_2_0_FW_FILE "firmware.bin" -#define QCA99X0_HW_2_0_OTP_FILE "otp.bin" #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 /* QCA9377 1.0 definitions */ #define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0" -#define QCA9377_HW_1_0_FW_FILE "firmware.bin" -#define QCA9377_HW_1_0_OTP_FILE "otp.bin" #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 /* QCA4019 1.0 definitions */ #define QCA4019_HW_1_0_DEV_VERSION 0x01000000 #define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0" -#define QCA4019_HW_1_0_FW_FILE "firmware.bin" -#define QCA4019_HW_1_0_OTP_FILE "otp.bin" #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index cdd8a307c55b..8133d7b5b956 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3173,7 +3173,6 @@ MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); MODULE_LICENSE("Dual BSD/GPL"); /* QCA988x 2.0 firmware files */ -MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 7eb40f54fdb5..254844b37d92 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4604,10 +4604,6 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", arg.service_map, arg.service_map_len); - /* only manually set fw features when not using FW IE format */ - if (ar->fw_api == 1 && ar->fw_version_build > 636) - set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); - if (ar->num_rf_chains > ar->max_spatial_stream) { ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n", ar->num_rf_chains, ar->max_spatial_stream); From 7ebf721d0d47150f6e327a6ae2692779495a2c2a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:44:51 +0300 Subject: [PATCH 100/164] ath10k: refactor firmware images to struct ath10k_fw_components To make it easier to share ath10k_core_fetch_board_data_api_n() with testmode.c refactor all firmware components to struct ath10k_fw_components. This structure will hold firmware related files, for example firmware-N.bin and board-N.bin. For firmware-N.bin create a new struct ath10k_fw_file which contains the actual firmware image as well as the parsed data from the image. Modify ath10k_core_start() to take struct ath10k_fw_components() as an argument which makes it possible in following patches to drop some ugly hacks from testmode.c. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 176 +++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 46 ++++-- drivers/net/wireless/ath/ath10k/debug.c | 28 ++-- drivers/net/wireless/ath/ath10k/mac.c | 3 +- drivers/net/wireless/ath/ath10k/swap.c | 22 ++- drivers/net/wireless/ath/ath10k/testmode.c | 61 ++++--- 6 files changed, 199 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 48389e0b87f6..b2efece5b32d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -538,7 +538,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) address = ar->hw_params.patch_load_addr; - if (!ar->otp_data || !ar->otp_len) { + if (!ar->normal_mode_fw.fw_file.otp_data || + !ar->normal_mode_fw.fw_file.otp_len) { ath10k_warn(ar, "failed to retrieve board id because of invalid otp\n"); return -ENODATA; @@ -546,9 +547,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd for board id\n", - address, ar->otp_len); + address, ar->normal_mode_fw.fw_file.otp_len); - ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + ret = ath10k_bmi_fast_download(ar, address, + ar->normal_mode_fw.fw_file.otp_data, + ar->normal_mode_fw.fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp for board id check: %d\n", ret); @@ -586,7 +589,9 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; int ret; - ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len); + ret = ath10k_download_board_data(ar, + ar->running_fw->board_data, + ar->running_fw->board_len); if (ret) { ath10k_err(ar, "failed to download board data: %d\n", ret); return ret; @@ -594,16 +599,20 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) /* OTP is optional */ - if (!ar->otp_data || !ar->otp_len) { + if (!ar->running_fw->fw_file.otp_data || + !ar->running_fw->fw_file.otp_len) { ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n", - ar->otp_data, ar->otp_len); + ar->running_fw->fw_file.otp_data, + ar->running_fw->fw_file.otp_len); return 0; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", - address, ar->otp_len); + address, ar->running_fw->fw_file.otp_len); - ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + ret = ath10k_bmi_fast_download(ar, address, + ar->running_fw->fw_file.otp_data, + ar->running_fw->fw_file.otp_len); if (ret) { ath10k_err(ar, "could not write otp (%d)\n", ret); return ret; @@ -627,46 +636,33 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) return 0; } -static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) +static int ath10k_download_fw(struct ath10k *ar) { u32 address, data_len; - const char *mode_name; const void *data; int ret; address = ar->hw_params.patch_load_addr; - switch (mode) { - case ATH10K_FIRMWARE_MODE_NORMAL: - data = ar->firmware_data; - data_len = ar->firmware_len; - mode_name = "normal"; - ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); - if (ret) { - ath10k_err(ar, "failed to configure fw code swap: %d\n", - ret); - return ret; - } - break; - case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf_firmware_data; - data_len = ar->testmode.utf_firmware_len; - mode_name = "utf"; - break; - default: - ath10k_err(ar, "unknown firmware mode: %d\n", mode); - return -EINVAL; + data = ar->running_fw->fw_file.firmware_data; + data_len = ar->running_fw->fw_file.firmware_len; + + ret = ath10k_swap_code_seg_configure(ar, + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + if (ret) { + ath10k_err(ar, "failed to configure fw code swap: %d\n", + ret); + return ret; } ath10k_dbg(ar, ATH10K_DBG_BOOT, - "boot uploading firmware image %p len %d mode %s\n", - data, data_len, mode_name); + "boot uploading firmware image %p len %d\n", + data, data_len); ret = ath10k_bmi_fast_download(ar, address, data, data_len); if (ret) { - ath10k_err(ar, "failed to download %s firmware: %d\n", - mode_name, ret); + ath10k_err(ar, "failed to download firmware: %d\n", + ret); return ret; } @@ -675,30 +671,30 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) static void ath10k_core_free_board_files(struct ath10k *ar) { - if (!IS_ERR(ar->board)) - release_firmware(ar->board); + if (!IS_ERR(ar->normal_mode_fw.board)) + release_firmware(ar->normal_mode_fw.board); - ar->board = NULL; - ar->board_data = NULL; - ar->board_len = 0; + ar->normal_mode_fw.board = NULL; + ar->normal_mode_fw.board_data = NULL; + ar->normal_mode_fw.board_len = 0; } static void ath10k_core_free_firmware_files(struct ath10k *ar) { - if (!IS_ERR(ar->firmware)) - release_firmware(ar->firmware); + if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware)) + release_firmware(ar->normal_mode_fw.fw_file.firmware); if (!IS_ERR(ar->cal_file)) release_firmware(ar->cal_file); ath10k_swap_code_seg_release(ar); - ar->otp_data = NULL; - ar->otp_len = 0; + ar->normal_mode_fw.fw_file.otp_data = NULL; + ar->normal_mode_fw.fw_file.otp_len = 0; - ar->firmware = NULL; - ar->firmware_data = NULL; - ar->firmware_len = 0; + ar->normal_mode_fw.fw_file.firmware = NULL; + ar->normal_mode_fw.fw_file.firmware_data = NULL; + ar->normal_mode_fw.fw_file.firmware_len = 0; ar->cal_file = NULL; } @@ -737,14 +733,14 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar) return -EINVAL; } - ar->board = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.board); - if (IS_ERR(ar->board)) - return PTR_ERR(ar->board); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); + if (IS_ERR(ar->normal_mode_fw.board)) + return PTR_ERR(ar->normal_mode_fw.board); - ar->board_data = ar->board->data; - ar->board_len = ar->board->size; + ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data; + ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size; return 0; } @@ -804,8 +800,8 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, "boot found board data for '%s'", boardname); - ar->board_data = board_ie_data; - ar->board_len = board_ie_len; + ar->normal_mode_fw.board_data = board_ie_data; + ar->normal_mode_fw.board_len = board_ie_len; ret = 0; goto out; @@ -838,12 +834,14 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, const u8 *data; int ret, ie_id; - ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); - if (IS_ERR(ar->board)) - return PTR_ERR(ar->board); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + filename); + if (IS_ERR(ar->normal_mode_fw.board)) + return PTR_ERR(ar->normal_mode_fw.board); - data = ar->board->data; - len = ar->board->size; + data = ar->normal_mode_fw.board->data; + len = ar->normal_mode_fw.board->size; /* magic has extra null byte padded */ magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; @@ -910,7 +908,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, } out: - if (!ar->board_data || !ar->board_len) { + if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) { ath10k_err(ar, "failed to fetch board data for %s from %s/%s\n", boardname, ar->hw_params.fw.dir, filename); @@ -978,7 +976,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) +static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file) { size_t magic_len, len, ie_len; int ie_id, i, index, bit, ret; @@ -987,15 +986,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) __le32 *timestamp, *version; /* first fetch the firmware file (firmware-*.bin) */ - ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name); - if (IS_ERR(ar->firmware)) { + fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, + name); + if (IS_ERR(fw_file->firmware)) { ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n", - ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware)); - return PTR_ERR(ar->firmware); + ar->hw_params.fw.dir, name, + PTR_ERR(fw_file->firmware)); + return PTR_ERR(fw_file->firmware); } - data = ar->firmware->data; - len = ar->firmware->size; + data = fw_file->firmware->data; + len = fw_file->firmware->size; /* magic also includes the null byte, check that as well */ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; @@ -1086,8 +1087,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) "found fw image ie (%zd B)\n", ie_len); - ar->firmware_data = data; - ar->firmware_len = ie_len; + fw_file->firmware_data = data; + fw_file->firmware_len = ie_len; break; case ATH10K_FW_IE_OTP_IMAGE: @@ -1095,8 +1096,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) "found otp image ie (%zd B)\n", ie_len); - ar->otp_data = data; - ar->otp_len = ie_len; + fw_file->otp_data = data; + fw_file->otp_len = ie_len; break; case ATH10K_FW_IE_WMI_OP_VERSION: @@ -1125,8 +1126,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw code swap image ie (%zd B)\n", ie_len); - ar->swap.firmware_codeswap_data = data; - ar->swap.firmware_codeswap_len = ie_len; + fw_file->codeswap_data = data; + fw_file->codeswap_len = ie_len; break; default: ath10k_warn(ar, "Unknown FW IE: %u\n", @@ -1141,7 +1142,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) data += ie_len; } - if (!ar->firmware_data || !ar->firmware_len) { + if (!fw_file->firmware_data || + !fw_file->firmware_len) { ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n", ar->hw_params.fw.dir, name); ret = -ENOMEDIUM; @@ -1165,28 +1167,32 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ar->fw_api = 5; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 4; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 3; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE, + &ar->normal_mode_fw.fw_file); if (ret == 0) goto success; ar->fw_api = 2; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE, + &ar->normal_mode_fw.fw_file); if (ret) return ret; @@ -1585,7 +1591,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return 0; } -int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) +int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, + const struct ath10k_fw_components *fw) { int status; u32 val; @@ -1594,6 +1601,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); + ar->running_fw = fw; + ath10k_bmi_start(ar); if (ath10k_init_configure_target(ar)) { @@ -1621,7 +1630,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) } } - status = ath10k_download_fw(ar, mode); + status = ath10k_download_fw(ar); if (status) goto err; @@ -1899,7 +1908,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar) mutex_lock(&ar->conf_mutex); - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL, + &ar->normal_mode_fw); if (ret) { ath10k_err(ar, "could not init core (%d)\n", ret); goto err_unlock; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 2d0cc92f3c5b..b377fd42c0a3 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -627,6 +627,27 @@ enum ath10k_tx_pause_reason { ATH10K_TX_PAUSE_MAX, }; +struct ath10k_fw_file { + const struct firmware *firmware; + + const void *firmware_data; + size_t firmware_len; + + const void *otp_data; + size_t otp_len; + + const void *codeswap_data; + size_t codeswap_len; +}; + +struct ath10k_fw_components { + const struct firmware *board; + const void *board_data; + size_t board_len; + + struct ath10k_fw_file fw_file; +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -714,23 +735,18 @@ struct ath10k { } fw; } hw_params; - const struct firmware *board; - const void *board_data; - size_t board_len; + /* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */ + struct ath10k_fw_components normal_mode_fw; - const void *otp_data; - size_t otp_len; - - const struct firmware *firmware; - const void *firmware_data; - size_t firmware_len; + /* READ-ONLY images of the running firmware, which can be either + * normal or UTF. Do not modify, release etc! + */ + const struct ath10k_fw_components *running_fw; const struct firmware *pre_cal_file; const struct firmware *cal_file; struct { - const void *firmware_codeswap_data; - size_t firmware_codeswap_len; struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; } swap; @@ -876,13 +892,12 @@ struct ath10k { struct { /* protected by conf_mutex */ - const struct firmware *utf; + struct ath10k_fw_components utf_mode_fw; char utf_version[32]; - const void *utf_firmware_data; - size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; + /* protected by data_lock */ bool utf_monitor; } testmode; @@ -919,7 +934,8 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, char *buf, size_t max_len); -int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode); +int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, + const struct ath10k_fw_components *fw_components); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); void ath10k_core_stop(struct ath10k *ar); int ath10k_core_register(struct ath10k *ar, u32 chip_id); diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index e7d441caa288..27787d23b2bd 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -126,6 +126,7 @@ EXPORT_SYMBOL(ath10k_info); void ath10k_debug_print_hwfw_info(struct ath10k *ar) { + const struct firmware *firmware; char fw_features[128] = {}; u32 crc = 0; @@ -144,8 +145,9 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), config_enabled(CONFIG_NL80211_TESTMODE)); - if (ar->firmware) - crc = crc32_le(0, ar->firmware->data, ar->firmware->size); + firmware = ar->normal_mode_fw.fw_file.firmware; + if (firmware) + crc = crc32_le(0, firmware->data, firmware->size); ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n", ar->hw->wiphy->fw_version, @@ -167,7 +169,8 @@ void ath10k_debug_print_board_info(struct ath10k *ar) ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x", ar->bd_api, boardinfo, - crc32_le(0, ar->board->data, ar->board->size)); + crc32_le(0, ar->normal_mode_fw.board->data, + ar->normal_mode_fw.board->size)); } void ath10k_debug_print_boot_info(struct ath10k *ar) @@ -2270,23 +2273,28 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file, len += scnprintf(buf + len, buf_len - len, "firmware-N.bin\t\t%08x\n", - crc32_le(0, ar->firmware->data, ar->firmware->size)); + crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data, + ar->normal_mode_fw.fw_file.firmware->size)); len += scnprintf(buf + len, buf_len - len, "athwlan\t\t\t%08x\n", - crc32_le(0, ar->firmware_data, ar->firmware_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data, + ar->normal_mode_fw.fw_file.firmware_len)); len += scnprintf(buf + len, buf_len - len, "otp\t\t\t%08x\n", - crc32_le(0, ar->otp_data, ar->otp_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.otp_data, + ar->normal_mode_fw.fw_file.otp_len)); len += scnprintf(buf + len, buf_len - len, "codeswap\t\t%08x\n", - crc32_le(0, ar->swap.firmware_codeswap_data, - ar->swap.firmware_codeswap_len)); + crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data, + ar->normal_mode_fw.fw_file.codeswap_len)); len += scnprintf(buf + len, buf_len - len, "board-N.bin\t\t%08x\n", - crc32_le(0, ar->board->data, ar->board->size)); + crc32_le(0, ar->normal_mode_fw.board->data, + ar->normal_mode_fw.board->size)); len += scnprintf(buf + len, buf_len - len, "board\t\t\t%08x\n", - crc32_le(0, ar->board_data, ar->board_len)); + crc32_le(0, ar->normal_mode_fw.board_data, + ar->normal_mode_fw.board_len)); ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index fb393596f236..56abbf2f2a59 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4376,7 +4376,8 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_off; } - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL, + &ar->normal_mode_fw); if (ret) { ath10k_err(ar, "Could not init core: %d\n", ret); goto err_power_down; diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c index 3ca3fae408a7..47d449bac86d 100644 --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -171,8 +171,13 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar, void ath10k_swap_code_seg_release(struct ath10k *ar) { ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info); - ar->swap.firmware_codeswap_data = NULL; - ar->swap.firmware_codeswap_len = 0; + + /* FIXME: these two assignments look to bein wrong place! Shouldn't + * they be in ath10k_core_free_firmware_files() like the rest? + */ + ar->normal_mode_fw.fw_file.codeswap_data = NULL; + ar->normal_mode_fw.fw_file.codeswap_len = 0; + ar->swap.firmware_swap_code_seg_info = NULL; } @@ -180,20 +185,23 @@ int ath10k_swap_code_seg_init(struct ath10k *ar) { int ret; struct ath10k_swap_code_seg_info *seg_info; + const void *codeswap_data; + size_t codeswap_len; - if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data) + codeswap_data = ar->normal_mode_fw.fw_file.codeswap_data; + codeswap_len = ar->normal_mode_fw.fw_file.codeswap_len; + + if (!codeswap_len || !codeswap_data) return 0; - seg_info = ath10k_swap_code_seg_alloc(ar, - ar->swap.firmware_codeswap_len); + seg_info = ath10k_swap_code_seg_alloc(ar, codeswap_len); if (!seg_info) { ath10k_err(ar, "failed to allocate fw code swap segment\n"); return -ENOMEM; } ret = ath10k_swap_code_seg_fill(ar, seg_info, - ar->swap.firmware_codeswap_data, - ar->swap.firmware_codeswap_len); + codeswap_data, codeswap_len); if (ret) { ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 1d5a2fdcbf56..480fad301fad 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,7 +139,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) +static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, + struct ath10k_fw_file *fw_file) { size_t len, magic_len, ie_len; struct ath10k_fw_ie *hdr; @@ -152,15 +153,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = request_firmware(&fw_file->firmware, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", filename, ret); return ret; } - data = ar->testmode.utf->data; - len = ar->testmode.utf->size; + data = fw_file->firmware->data; + len = fw_file->firmware->size; /* FIXME: call release_firmware() in error cases */ @@ -222,8 +223,8 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) "testmode found fw image ie (%zd B)\n", ie_len); - ar->testmode.utf_firmware_data = data; - ar->testmode.utf_firmware_len = ie_len; + fw_file->firmware_data = data; + fw_file->firmware_len = ie_len; break; case ATH10K_FW_IE_WMI_OP_VERSION: if (ie_len != sizeof(u32)) @@ -245,7 +246,7 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) data += ie_len; } - if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + if (!fw_file->firmware_data || !fw_file->firmware_len) { ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); ret = -EINVAL; goto err; @@ -254,12 +255,13 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) return 0; err: - release_firmware(ar->testmode.utf); + release_firmware(fw_file->firmware); return ret; } -static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) +static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, + struct ath10k_fw_file *fw_file) { char filename[100]; int ret; @@ -268,7 +270,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = request_firmware(&fw_file->firmware, filename, ar->dev); if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", filename, ret); @@ -282,23 +284,24 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) */ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; - ar->testmode.utf_firmware_data = ar->testmode.utf->data; - ar->testmode.utf_firmware_len = ar->testmode.utf->size; + fw_file->firmware_data = fw_file->firmware->data; + fw_file->firmware_len = fw_file->firmware->size; return 0; } static int ath10k_tm_fetch_firmware(struct ath10k *ar) { + struct ath10k_fw_components *utf_mode_fw; int ret; - ret = ath10k_tm_fetch_utf_firmware_api_2(ar); + ret = ath10k_tm_fetch_utf_firmware_api_2(ar, &ar->testmode.utf_mode_fw.fw_file); if (ret == 0) { ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); - return 0; + goto out; } - ret = ath10k_tm_fetch_utf_firmware_api_1(ar); + ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file); if (ret) { ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); return ret; @@ -306,6 +309,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); +out: + utf_mode_fw = &ar->testmode.utf_mode_fw; + + /* Use the same board data file as the normal firmware uses (but + * it's still "owned" by normal_mode_fw so we shouldn't free it. + */ + utf_mode_fw->board_data = ar->normal_mode_fw.board_data; + utf_mode_fw->board_len = ar->normal_mode_fw.board_len; + + if (!utf_mode_fw->fw_file.otp_data) { + ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware"); + utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data; + utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len; + } + return 0; } @@ -329,7 +347,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err; } - if (WARN_ON(ar->testmode.utf != NULL)) { + if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) { /* utf image is already downloaded, it shouldn't be */ ret = -EEXIST; goto err; @@ -364,7 +382,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err_fw_features; } - ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF); + ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF, + &ar->testmode.utf_mode_fw); if (ret) { ath10k_err(ar, "failed to start core (testmode): %d\n", ret); ar->state = ATH10K_STATE_OFF; @@ -393,8 +412,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf); - ar->testmode.utf = NULL; + release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); + ar->testmode.utf_mode_fw.fw_file.firmware = NULL; err: mutex_unlock(&ar->conf_mutex); @@ -420,8 +439,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar) sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf); - ar->testmode.utf = NULL; + release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); + ar->testmode.utf_mode_fw.fw_file.firmware = NULL; ar->state = ATH10K_STATE_OFF; } From 453173550256542c20b24a8d85b806941b77ac76 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:05 +0300 Subject: [PATCH 101/164] ath10k: move fw_version inside struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 13 +++++++++---- drivers/net/wireless/ath/ath10k/core.h | 3 ++- drivers/net/wireless/ath/ath10k/testmode.c | 12 ++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b2efece5b32d..015241aec608 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1039,15 +1039,15 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, switch (ie_id) { case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1) + if (ie_len > sizeof(fw_file->fw_version) - 1) break; - memcpy(ar->hw->wiphy->fw_version, data, ie_len); - ar->hw->wiphy->fw_version[ie_len] = '\0'; + memcpy(fw_file->fw_version, data, ie_len); + fw_file->fw_version[ie_len] = '\0'; ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw version %s\n", - ar->hw->wiphy->fw_version); + fw_file->fw_version); break; case ATH10K_FW_IE_TIMESTAMP: if (ie_len != sizeof(u32)) @@ -1866,6 +1866,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_power_down; } + BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) != + sizeof(ar->normal_mode_fw.fw_file.fw_version)); + memcpy(ar->hw->wiphy->fw_version, ar->normal_mode_fw.fw_file.fw_version, + sizeof(ar->hw->wiphy->fw_version)); + ath10k_debug_print_hwfw_info(ar); ret = ath10k_core_pre_cal_download(ar); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b377fd42c0a3..432b1590f6e6 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -630,6 +630,8 @@ enum ath10k_tx_pause_reason { struct ath10k_fw_file { const struct firmware *firmware; + char fw_version[ETHTOOL_FWVERS_LEN]; + const void *firmware_data; size_t firmware_len; @@ -893,7 +895,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - char utf_version[32]; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 480fad301fad..2c4a5d31cf0c 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -205,15 +205,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, switch (ie_id) { case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(ar->testmode.utf_version) - 1) + if (ie_len > sizeof(fw_file->fw_version) - 1) break; - memcpy(ar->testmode.utf_version, data, ie_len); - ar->testmode.utf_version[ie_len] = '\0'; + memcpy(fw_file->fw_version, data, ie_len); + fw_file->fw_version[ie_len] = '\0'; ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw utf version %s\n", - ar->testmode.utf_version); + fw_file->fw_version); break; case ATH10K_FW_IE_TIMESTAMP: /* ignore timestamp, but don't warn about it either */ @@ -392,8 +392,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->state = ATH10K_STATE_UTF; - if (strlen(ar->testmode.utf_version) > 0) - ver = ar->testmode.utf_version; + if (strlen(ar->testmode.utf_mode_fw.fw_file.fw_version) > 0) + ver = ar->testmode.utf_mode_fw.fw_file.fw_version; else ver = "API 1"; From c4cdf753ed4287467248126a4fac072fbba53b31 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:18 +0300 Subject: [PATCH 102/164] ath10k: move fw_features to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 28 ++++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 5 ++-- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 9 ++++--- drivers/net/wireless/ath/ath10k/mac.c | 14 ++++++----- drivers/net/wireless/ath/ath10k/testmode.c | 14 ----------- drivers/net/wireless/ath/ath10k/wmi.c | 5 ++-- drivers/net/wireless/ath/ath10k/wow.c | 7 +++--- 8 files changed, 39 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 015241aec608..71b8ca71d1da 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -261,7 +261,7 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, int i; for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) { - if (test_bit(i, ar->fw_features)) { + if (test_bit(i, ar->normal_mode_fw.fw_file.fw_features)) { if (len > 0) len += scnprintf(buf + len, buf_len - len, ","); @@ -627,7 +627,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, - ar->fw_features)) && + ar->running_fw->fw_file.fw_features)) && result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; @@ -1074,13 +1074,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, ath10k_dbg(ar, ATH10K_DBG_BOOT, "Enabling feature bit: %i\n", i); - __set_bit(i, ar->fw_features); + __set_bit(i, fw_file->fw_features); } } ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "", - ar->fw_features, - sizeof(ar->fw_features)); + ar->running_fw->fw_file.fw_features, + sizeof(fw_file->fw_features)); break; case ATH10K_FW_IE_FW_IMAGE: ath10k_dbg(ar, ATH10K_DBG_BOOT, @@ -1430,8 +1430,10 @@ static void ath10k_core_restart(struct work_struct *work) static int ath10k_core_init_firmware_features(struct ath10k *ar) { - if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) && - !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; + + if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) && + !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well"); return -EINVAL; } @@ -1450,7 +1452,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) break; case ATH10K_CRYPT_MODE_SW: if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, - ar->fw_features)) { + fw_file->fw_features)) { ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware"); return -EINVAL; } @@ -1469,7 +1471,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) if (rawmode) { if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, - ar->fw_features)) { + fw_file->fw_features)) { ath10k_err(ar, "rawmode = 1 requires support from firmware"); return -EINVAL; } @@ -1495,9 +1497,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) * ATH10K_FW_IE_WMI_OP_VERSION. */ if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { - if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { + if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, - ar->fw_features)) + fw_file->fw_features)) ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2; else ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; @@ -1553,7 +1555,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->max_spatial_stream = ar->hw_params.max_spatial_stream; if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, - ar->fw_features)) + fw_file->fw_features)) ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC; else ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC; @@ -1621,7 +1623,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, * to set the clock source once the target is initialized. */ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1); if (status) { ath10k_err(ar, "could not write to skip_clock_init: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 432b1590f6e6..18e21b4fe034 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -632,6 +632,8 @@ struct ath10k_fw_file { char fw_version[ETHTOOL_FWVERS_LEN]; + DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); + const void *firmware_data; size_t firmware_len; @@ -675,8 +677,6 @@ struct ath10k { /* protected by conf_mutex */ bool ani_enabled; - DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); - bool p2p; struct { @@ -895,7 +895,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version op_version; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 9390897a00c6..5b777c24d2ba 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -966,7 +966,7 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar, int len = ieee80211_hdrlen(hdr->frame_control); if (!test_bit(ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) len = round_up(len, 4); return len; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 9baa2e677f8a..6269c610b0a3 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -267,7 +267,8 @@ static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; size_t size; - if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) return; size = sizeof(*htt->tx_q_state.vaddr); @@ -282,7 +283,8 @@ static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt) size_t size; int ret; - if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) return 0; htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS; @@ -513,7 +515,8 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) info |= SM(htt->tx_q_state.type, HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE); - if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, + ar->running_fw->fw_file.fw_features)) info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID; cfg = &cmd->frag_desc_bank_cfg; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 56abbf2f2a59..0fd0fc111c40 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1772,7 +1772,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) if (enable_ps && ath10k_mac_num_vifs_started(ar) > 1 && !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n", arvif->vdev_id); enable_ps = false; @@ -2060,7 +2060,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, } if (sta->mfp && - test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) { + test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, + ar->running_fw->fw_file.fw_features)) { arg->peer_flags |= ar->wmi.peer_flags->pmf; } } @@ -3207,7 +3208,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, */ if (ar->htt.target_version_major < 3 && (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) && - !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, ar->fw_features)) + !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, + ar->running_fw->fw_file.fw_features)) return ATH10K_HW_TXRX_MGMT; /* Workaround: @@ -3394,7 +3396,7 @@ ath10k_mac_tx_h_get_txpath(struct ath10k *ar, return ATH10K_MAC_TX_HTT; case ATH10K_HW_TXRX_MGMT: if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) return ATH10K_MAC_TX_WMI_MGMT; else if (ar->htt.target_version_major >= 3) return ATH10K_MAC_TX_HTT; @@ -4435,7 +4437,7 @@ static int ath10k_start(struct ieee80211_hw *hw) } if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, - ar->fw_features)) { + ar->running_fw->fw_file.fw_features)) { ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, WMI_CCA_DETECT_LEVEL_AUTO, WMI_CCA_DETECT_MARGIN_AUTO); @@ -7694,7 +7696,7 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; - if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->normal_mode_fw.fw_file.fw_features)) ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_P2P_CLIENT) | diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 2c4a5d31cf0c..102539409f54 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -362,14 +362,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) spin_lock_bh(&ar->data_lock); ar->testmode.utf_monitor = true; spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != - sizeof(ar->testmode.orig_fw_features)); - memcpy(ar->testmode.orig_fw_features, ar->fw_features, - sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ar->testmode.op_version; ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", @@ -407,9 +401,6 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ath10k_hif_power_down(ar); err_fw_features: - /* return the original firmware features */ - memcpy(ar->fw_features, ar->testmode.orig_fw_features, - sizeof(ar->fw_features)); ar->wmi.op_version = ar->testmode.orig_wmi_op_version; release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); @@ -434,11 +425,6 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar) spin_unlock_bh(&ar->data_lock); - /* return the original firmware features */ - memcpy(ar->fw_features, ar->testmode.orig_fw_features, - sizeof(ar->fw_features)); - ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); ar->testmode.utf_mode_fw.fw_file.firmware = NULL; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 254844b37d92..d5279ce32974 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2149,7 +2149,8 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, u32 msdu_len; u32 len; - if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { + if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, + ar->running_fw->fw_file.fw_features)) { ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; ev_hdr = &ev_v2->hdr.v1; pull_len = sizeof(*ev_v2); @@ -4634,7 +4635,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, - ar->fw_features)) + ar->running_fw->fw_file.fw_features)) ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC + ar->max_num_vdevs; else diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index 8e02b381990f..77100d42f401 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -233,7 +233,7 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->fw_features))) { + ar->running_fw->fw_file.fw_features))) { ret = 1; goto exit; } @@ -285,7 +285,7 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw) mutex_lock(&ar->conf_mutex); if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->fw_features))) { + ar->running_fw->fw_file.fw_features))) { ret = 1; goto exit; } @@ -325,7 +325,8 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw) int ath10k_wow_init(struct ath10k *ar) { - if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, ar->fw_features)) + if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, + ar->running_fw->fw_file.fw_features)) return 0; if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) From bf3c13ab49965f0517b579dc490d612d074d535a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:33 +0300 Subject: [PATCH 103/164] ath10k: move wmi_op_version to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 20 ++++++++++---------- drivers/net/wireless/ath/ath10k/core.h | 5 ++--- drivers/net/wireless/ath/ath10k/debug.c | 2 +- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/testmode.c | 17 ++++++----------- drivers/net/wireless/ath/ath10k/wmi.c | 4 ++-- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 71b8ca71d1da..a7c99355a7c2 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1106,10 +1106,10 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, version = (__le32 *)data; - ar->wmi.op_version = le32_to_cpup(version); + fw_file->wmi_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n", - ar->wmi.op_version); + fw_file->wmi_op_version); break; case ATH10K_FW_IE_HTT_OP_VERSION: if (ie_len != sizeof(u32)) @@ -1438,9 +1438,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return -EINVAL; } - if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) { + if (fw_file->wmi_op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) { ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n", - ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version); + ATH10K_FW_WMI_OP_VERSION_MAX, fw_file->wmi_op_version); return -EINVAL; } @@ -1496,19 +1496,19 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) /* Backwards compatibility for firmwares without * ATH10K_FW_IE_WMI_OP_VERSION. */ - if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { + if (fw_file->wmi_op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) { if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features)) - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_2; else - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; } else { - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_MAIN; } } - switch (ar->wmi.op_version) { + switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->max_num_peers = TARGET_NUM_PEERS; ar->max_num_stations = TARGET_NUM_STATIONS; @@ -1570,7 +1570,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) * ATH10K_FW_IE_HTT_OP_VERSION. */ if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { - switch (ar->wmi.op_version) { + switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; break; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 18e21b4fe034..7d709f848fac 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -139,7 +139,6 @@ struct ath10k_mem_chunk { }; struct ath10k_wmi { - enum ath10k_fw_wmi_op_version op_version; enum ath10k_htc_ep_id eid; struct completion service_ready; struct completion unified_ready; @@ -634,6 +633,8 @@ struct ath10k_fw_file { DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); + enum ath10k_fw_wmi_op_version wmi_op_version; + const void *firmware_data; size_t firmware_len; @@ -895,8 +896,6 @@ struct ath10k { struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; - enum ath10k_fw_wmi_op_version orig_wmi_op_version; - enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 27787d23b2bd..8a63ce5c6e09 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -178,7 +178,7 @@ void ath10k_debug_print_boot_info(struct ath10k *ar) ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n", ar->htt.target_version_major, ar->htt.target_version_minor, - ar->wmi.op_version, + ar->normal_mode_fw.fw_file.wmi_op_version, ar->htt.op_version, ath10k_cal_mode_str(ar->cal_mode), ar->max_num_stations, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0fd0fc111c40..5fb912acc0a8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7786,7 +7786,7 @@ int ath10k_mac_register(struct ath10k *ar) */ ar->hw->offchannel_tx_hw_queue = IEEE80211_MAX_QUEUES - 1; - switch (ar->wmi.op_version) { + switch (ar->running_fw->fw_file.wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->hw->wiphy->iface_combinations = ath10k_if_comb; ar->hw->wiphy->n_iface_combinations = diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 102539409f54..3d4418969697 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -230,9 +230,9 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, if (ie_len != sizeof(u32)) break; version = (__le32 *)data; - ar->testmode.op_version = le32_to_cpup(version); + fw_file->wmi_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", - ar->testmode.op_version); + fw_file->wmi_op_version); break; default: ath10k_warn(ar, "Unknown testmode FW IE: %u\n", @@ -283,7 +283,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, * correct WMI interface. */ - ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; fw_file->firmware_data = fw_file->firmware->data; fw_file->firmware_len = fw_file->firmware->size; @@ -363,17 +363,14 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->testmode.utf_monitor = true; spin_unlock_bh(&ar->data_lock); - ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - ar->wmi.op_version = ar->testmode.op_version; - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", - ar->wmi.op_version); + ar->testmode.utf_mode_fw.fw_file.wmi_op_version); ret = ath10k_hif_power_up(ar); if (ret) { ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); ar->state = ATH10K_STATE_OFF; - goto err_fw_features; + goto err_release_utf_mode_fw; } ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF, @@ -400,9 +397,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) err_power_down: ath10k_hif_power_down(ar); -err_fw_features: - ar->wmi.op_version = ar->testmode.orig_wmi_op_version; - +err_release_utf_mode_fw: release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware); ar->testmode.utf_mode_fw.fw_file.firmware = NULL; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index d5279ce32974..a1afb2e2b05a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -7865,7 +7865,7 @@ static const struct wmi_ops wmi_10_4_ops = { int ath10k_wmi_attach(struct ath10k *ar) { - switch (ar->wmi.op_version) { + switch (ar->running_fw->fw_file.wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_10_4: ar->wmi.ops = &wmi_10_4_ops; ar->wmi.cmd = &wmi_10_4_cmd_map; @@ -7907,7 +7907,7 @@ int ath10k_wmi_attach(struct ath10k *ar) case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: ath10k_err(ar, "unsupported WMI op version: %d\n", - ar->wmi.op_version); + ar->running_fw->fw_file.wmi_op_version); return -EINVAL; } From 77561f9394f8553cce487b12b15b4879ecbaf6d7 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:45:47 +0300 Subject: [PATCH 104/164] ath10k: move htt_op_version to struct ath10k_fw_file Preparation for testmode.c to use ath10k_core_fetch_board_data_api_n(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 12 ++++++------ drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 2 +- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/htt.h | 1 - drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/testmode.c | 1 + 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index a7c99355a7c2..4af01afdaf6c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1117,10 +1117,10 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, version = (__le32 *)data; - ar->htt.op_version = le32_to_cpup(version); + fw_file->htt_op_version = le32_to_cpup(version); ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n", - ar->htt.op_version); + fw_file->htt_op_version); break; case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE: ath10k_dbg(ar, ATH10K_DBG_BOOT, @@ -1569,18 +1569,18 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) /* Backwards compatibility for firmwares without * ATH10K_FW_IE_HTT_OP_VERSION. */ - if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { + if (fw_file->htt_op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) { switch (fw_file->wmi_op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_MAIN; break; case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2_4: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_10_1; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1; break; case ATH10K_FW_WMI_OP_VERSION_TLV: - ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV; break; case ATH10K_FW_WMI_OP_VERSION_10_4: case ATH10K_FW_WMI_OP_VERSION_UNSET: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7d709f848fac..55a28c08e898 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -634,6 +634,7 @@ struct ath10k_fw_file { DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version wmi_op_version; + enum ath10k_fw_htt_op_version htt_op_version; const void *firmware_data; size_t firmware_len; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 8a63ce5c6e09..e2511550fbb8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -179,7 +179,7 @@ void ath10k_debug_print_boot_info(struct ath10k *ar) ar->htt.target_version_major, ar->htt.target_version_minor, ar->normal_mode_fw.fw_file.wmi_op_version, - ar->htt.op_version, + ar->normal_mode_fw.fw_file.htt_op_version, ath10k_cal_mode_str(ar->cal_mode), ar->max_num_stations, test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags), diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index ee79512b1fcc..130cd9502021 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -183,7 +183,7 @@ int ath10k_htt_init(struct ath10k *ar) 8 + /* llc snap */ 2; /* ip4 dscp or ip6 priority */ - switch (ar->htt.op_version) { + switch (ar->running_fw->fw_file.htt_op_version) { case ATH10K_FW_HTT_OP_VERSION_10_4: ar->htt.t2h_msg_types = htt_10_4_t2h_msg_types; ar->htt.t2h_msg_types_max = HTT_10_4_T2H_NUM_MSGS; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index ee7c8f8f8073..911c535d0863 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1562,7 +1562,6 @@ struct ath10k_htt { u8 target_version_major; u8 target_version_minor; struct completion target_version_received; - enum ath10k_fw_htt_op_version op_version; u8 max_num_amsdu; u8 max_num_ampdu; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 5fb912acc0a8..67cf004b685a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3359,7 +3359,7 @@ bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) */ return (ar->htt.target_version_major >= 3 && ar->htt.target_version_minor >= 4 && - ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV); + ar->running_fw->fw_file.htt_op_version == ATH10K_FW_HTT_OP_VERSION_TLV); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 3d4418969697..daf04d74c6d0 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -284,6 +284,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, */ fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1; fw_file->firmware_data = fw_file->firmware->data; fw_file->firmware_len = fw_file->firmware->size; From 9dfe240b4d684f17efa861e92e45dc949b0049ed Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:46:01 +0300 Subject: [PATCH 105/164] ath10k: switch testmode to use ath10k_core_fetch_firmware_api_n() Now that all firmware-N.bin related are within struct ath10k_fw_file we can switch to use ath10k_core_fetch_firmware_api_n() and delete almost identical ath10k_tm_fetch_utf_firmware_api_2(). Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 2 + drivers/net/wireless/ath/ath10k/testmode.c | 124 +-------------------- 3 files changed, 6 insertions(+), 124 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 4af01afdaf6c..db9437a72ba4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -976,8 +976,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, - struct ath10k_fw_file *fw_file) +int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file) { size_t magic_len, len, ie_len; int ie_id, i, index, bit, ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 55a28c08e898..f3553dc11c5d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -933,6 +933,8 @@ void ath10k_core_destroy(struct ath10k *ar); void ath10k_core_get_fw_features_str(struct ath10k *ar, char *buf, size_t max_len); +int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, + struct ath10k_fw_file *fw_file); int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, const struct ath10k_fw_components *fw_components); diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index daf04d74c6d0..120f4234d3b0 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,127 +139,6 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar, - struct ath10k_fw_file *fw_file) -{ - size_t len, magic_len, ie_len; - struct ath10k_fw_ie *hdr; - char filename[100]; - __le32 *version; - const u8 *data; - int ie_id, ret; - - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); - - /* load utf firmware image */ - ret = request_firmware(&fw_file->firmware, filename, ar->dev); - if (ret) { - ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); - return ret; - } - - data = fw_file->firmware->data; - len = fw_file->firmware->size; - - /* FIXME: call release_firmware() in error cases */ - - /* magic also includes the null byte, check that as well */ - magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; - - if (len < magic_len) { - ath10k_err(ar, "utf firmware file is too small to contain magic\n"); - ret = -EINVAL; - goto err; - } - - if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { - ath10k_err(ar, "invalid firmware magic\n"); - ret = -EINVAL; - goto err; - } - - /* jump over the padding */ - magic_len = ALIGN(magic_len, 4); - - len -= magic_len; - data += magic_len; - - /* loop elements */ - while (len > sizeof(struct ath10k_fw_ie)) { - hdr = (struct ath10k_fw_ie *)data; - - ie_id = le32_to_cpu(hdr->id); - ie_len = le32_to_cpu(hdr->len); - - len -= sizeof(*hdr); - data += sizeof(*hdr); - - if (len < ie_len) { - ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", - ie_id, len, ie_len); - ret = -EINVAL; - goto err; - } - - switch (ie_id) { - case ATH10K_FW_IE_FW_VERSION: - if (ie_len > sizeof(fw_file->fw_version) - 1) - break; - - memcpy(fw_file->fw_version, data, ie_len); - fw_file->fw_version[ie_len] = '\0'; - - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, - "testmode found fw utf version %s\n", - fw_file->fw_version); - break; - case ATH10K_FW_IE_TIMESTAMP: - /* ignore timestamp, but don't warn about it either */ - break; - case ATH10K_FW_IE_FW_IMAGE: - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, - "testmode found fw image ie (%zd B)\n", - ie_len); - - fw_file->firmware_data = data; - fw_file->firmware_len = ie_len; - break; - case ATH10K_FW_IE_WMI_OP_VERSION: - if (ie_len != sizeof(u32)) - break; - version = (__le32 *)data; - fw_file->wmi_op_version = le32_to_cpup(version); - ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", - fw_file->wmi_op_version); - break; - default: - ath10k_warn(ar, "Unknown testmode FW IE: %u\n", - le32_to_cpu(hdr->id)); - break; - } - /* jump over the padding */ - ie_len = ALIGN(ie_len, 4); - - len -= ie_len; - data += ie_len; - } - - if (!fw_file->firmware_data || !fw_file->firmware_len) { - ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); - ret = -EINVAL; - goto err; - } - - return 0; - -err: - release_firmware(fw_file->firmware); - - return ret; -} - static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, struct ath10k_fw_file *fw_file) { @@ -296,7 +175,8 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar) struct ath10k_fw_components *utf_mode_fw; int ret; - ret = ath10k_tm_fetch_utf_firmware_api_2(ar, &ar->testmode.utf_mode_fw.fw_file); + ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_UTF_API2_FILE, + &ar->testmode.utf_mode_fw.fw_file); if (ret == 0) { ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); goto out; From 1fe63c9ca8913eb7af6c428cf81abad29e0bc9d6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 20 Apr 2016 19:46:16 +0300 Subject: [PATCH 106/164] ath10k: remove enum ath10k_swap_code_seg_bin_type It's not needed for anything so just get rid of it. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 +-- drivers/net/wireless/ath/ath10k/swap.c | 22 ++++++---------------- drivers/net/wireless/ath/ath10k/swap.h | 9 +-------- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index db9437a72ba4..e94cb87380d2 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -647,8 +647,7 @@ static int ath10k_download_fw(struct ath10k *ar) data = ar->running_fw->fw_file.firmware_data; data_len = ar->running_fw->fw_file.firmware_len; - ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + ret = ath10k_swap_code_seg_configure(ar); if (ret) { ath10k_err(ar, "failed to configure fw code swap: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c index 47d449bac86d..0c5f5863dac8 100644 --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -134,27 +134,17 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len) return seg_info; } -int ath10k_swap_code_seg_configure(struct ath10k *ar, - enum ath10k_swap_code_seg_bin_type type) +int ath10k_swap_code_seg_configure(struct ath10k *ar) { int ret; struct ath10k_swap_code_seg_info *seg_info = NULL; - switch (type) { - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW: - if (!ar->swap.firmware_swap_code_seg_info) - return 0; - - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n"); - seg_info = ar->swap.firmware_swap_code_seg_info; - break; - default: - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP: - case ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF: - ath10k_warn(ar, "ignoring unknown code swap binary type %d\n", - type); + if (!ar->swap.firmware_swap_code_seg_info) return 0; - } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n"); + + seg_info = ar->swap.firmware_swap_code_seg_info; ret = ath10k_bmi_write_memory(ar, seg_info->target_addr, &seg_info->seg_hw_info, diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h index 5c89952dd20f..36991c7b07a0 100644 --- a/drivers/net/wireless/ath/ath10k/swap.h +++ b/drivers/net/wireless/ath/ath10k/swap.h @@ -39,12 +39,6 @@ union ath10k_swap_code_seg_item { struct ath10k_swap_code_seg_tail tail; } __packed; -enum ath10k_swap_code_seg_bin_type { - ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF, -}; - struct ath10k_swap_code_seg_hw_info { /* Swap binary image size */ __le32 swap_size; @@ -64,8 +58,7 @@ struct ath10k_swap_code_seg_info { dma_addr_t paddr[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED]; }; -int ath10k_swap_code_seg_configure(struct ath10k *ar, - enum ath10k_swap_code_seg_bin_type type); +int ath10k_swap_code_seg_configure(struct ath10k *ar); void ath10k_swap_code_seg_release(struct ath10k *ar); int ath10k_swap_code_seg_init(struct ath10k *ar); From 06d05463ee337e85e42c6073b6f2f46fbfb05b96 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Apr 2016 23:59:31 +0200 Subject: [PATCH 107/164] rtl8xxxu: hide unused tables The references to some arrays in the rtl8xxxu driver were moved inside of an #ifdef, but the symbols remain outside, resulting in build warnings: rtl8xxxu/rtl8xxxu.c:1506:33: error: 'rtl8188ru_radioa_1t_highpa_table' defined but not used rtl8xxxu/rtl8xxxu.c:1431:33: error: 'rtl8192cu_radioa_1t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:1407:33: error: 'rtl8192cu_radiob_2t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:1332:33: error: 'rtl8192cu_radioa_2t_init_table' defined but not used rtl8xxxu/rtl8xxxu.c:239:35: error: 'rtl8192c_power_base' defined but not used rtl8xxxu/rtl8xxxu.c:217:35: error: 'rtl8188r_power_base' defined but not used This adds an extra #ifdef around them to shut up the warnings. Signed-off-by: Arnd Bergmann Fixes: 2fc0b8e5a17d ("rtl8xxxu: Add TX power base values for gen1 parts") Fixes: 4062b8ffec36 ("rtl8xxxu: Move PHY RF init into device specific functions") Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 928ca56f751c..0ba84b5fe0d6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -214,6 +214,7 @@ static struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = { {0xffff, 0xff}, }; +#ifdef CONFIG_RTL8XXXU_UNTESTED static struct rtl8xxxu_power_base rtl8188r_power_base = { .reg_0e00 = 0x06080808, .reg_0e04 = 0x00040406, @@ -257,6 +258,7 @@ static struct rtl8xxxu_power_base rtl8192c_power_base = { .reg_084c = 0x0b0c0d0e, .reg_0868 = 0x01030509, }; +#endif static struct rtl8xxxu_power_base rtl8723a_power_base = { .reg_0e00 = 0x0a0c0c0c, @@ -1329,6 +1331,7 @@ static struct rtl8xxxu_rfregval rtl8723bu_radioa_1t_init_table[] = { {0xff, 0xffffffff} }; +#ifdef CONFIG_RTL8XXXU_UNTESTED static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = { {0x00, 0x00030159}, {0x01, 0x00031284}, {0x02, 0x00098000}, {0x03, 0x00018c63}, @@ -1577,6 +1580,7 @@ static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { {0x00, 0x00030159}, {0xff, 0xffffffff} }; +#endif static struct rtl8xxxu_rfregval rtl8192eu_radioa_init_table[] = { {0x7f, 0x00000082}, {0x81, 0x0003fc00}, From cd84042ce9040ad038e958bc67a46fcfc015c736 Mon Sep 17 00:00:00 2001 From: "Vittorio Gambaletta (VittGam)" Date: Mon, 11 Apr 2016 04:48:54 +0200 Subject: [PATCH 108/164] ath9k: Add a module parameter to invert LED polarity. The LED can be active high instead of active low on some hardware. Add the led_active_high module parameter. It defaults to -1 to obey platform data as before. Setting the parameter to 1 or 0 will force the LED respectively active high or active low. Cc: Cc: Cc: Cc: Signed-off-by: Vittorio Gambaletta Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fb702c48a233..535b1644501c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -49,6 +49,10 @@ int ath9k_led_blink; module_param_named(blink, ath9k_led_blink, int, 0444); MODULE_PARM_DESC(blink, "Enable LED blink on activity"); +static int ath9k_led_active_high = -1; +module_param_named(led_active_high, ath9k_led_active_high, int, 0444); +MODULE_PARM_DESC(led_active_high, "Invert LED polarity"); + static int ath9k_btcoex_enable; module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); @@ -600,6 +604,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, if (ret) return ret; + if (ath9k_led_active_high != -1) + ah->config.led_active_high = ath9k_led_active_high == 1; + /* * Enable WLAN/BT RX Antenna diversity only when: * From 0f9edcdd88a993914fa1d1dc369b35dc503979db Mon Sep 17 00:00:00 2001 From: "Vittorio Gambaletta (VittGam)" Date: Mon, 11 Apr 2016 04:48:55 +0200 Subject: [PATCH 109/164] ath9k: Fix LED polarity for some Mini PCI AR9220 MB92 cards. The Wistron DNMA-92 and Compex WLM200NX have inverted LED polarity (active high instead of active low). The same PCI Subsystem ID is used by both cards, which are based on the same Atheros MB92 design. Cc: Cc: Cc: Cc: Signed-off-by: Vittorio Gambaletta Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e6fef1be9977..7cdaf40c3057 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -28,6 +28,16 @@ static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ + +#ifdef CONFIG_ATH9K_PCOEM + /* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0029, + PCI_VENDOR_ID_ATHEROS, + 0x2096), + .driver_data = ATH9K_PCI_LED_ACT_HI }, +#endif + { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ #ifdef CONFIG_ATH9K_PCOEM From 25d217d6e0723481bf90db1d8be02ab475d16002 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:39 -0700 Subject: [PATCH 110/164] wcn36xx: Clean up wcn36xx_smd_send_beacon Needed for coming improvements. No functional changes. Signed-off-by: Pontus Fuchs [bjorn: restored BEACON_TEMPLATE_SIZE define to 0x180] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 5 ++++- drivers/net/wireless/ath/wcn36xx/smd.c | 12 +++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index b947de0fb2e5..d713204f755d 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2884,11 +2884,14 @@ struct update_beacon_rsp_msg { struct wcn36xx_hal_send_beacon_req_msg { struct wcn36xx_hal_msg_header header; + /* length of the template + 6. Only qcom knows why */ + u32 beacon_length6; + /* length of the template. */ u32 beacon_length; /* Beacon data. */ - u8 beacon[BEACON_TEMPLATE_SIZE]; + u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)]; u8 bssid[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 74f56a81ad9a..ff3ed2461a69 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1380,19 +1380,17 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); - /* TODO need to find out why this is needed? */ - msg_body.beacon_length = skb_beacon->len + 6; + msg_body.beacon_length = skb_beacon->len; + /* TODO need to find out why + 6 is needed */ + msg_body.beacon_length6 = msg_body.beacon_length + 6; - if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { - memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); - memcpy(&(msg_body.beacon[4]), skb_beacon->data, - skb_beacon->len); - } else { + if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) { wcn36xx_err("Beacon is to big: beacon size=%d\n", msg_body.beacon_length); ret = -ENOMEM; goto out; } + memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len); memcpy(msg_body.bssid, vif->addr, ETH_ALEN); /* TODO need to find out why this is needed? */ From 91c3eeba45e13ab7edfb50610df8672d52809394 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:40 -0700 Subject: [PATCH 111/164] wcn36xx: Pad TIM PVM if needed The wcn36xx FW expects a fixed size TIM PVM in the beacon template. If supplied with a shorter than expected PVM it will overwrite the IE following the TIM. Squashed with fix from Jason Mobarak : Patch "wcn36xx: Pad TIM PVM if needed" has caused a regression in mesh beaconing. The field tim_off is always 0 for mesh mode, and thus pvm_len (referring to the TIM length field) and pad are both incorrectly calculated. Thus, msg_body.beacon_length is incorrectly calculated for mesh mode. Fix this. Signed-off-by: Pontus Fuchs Signed-off-by: Jason Mobarak [bjorn: squashed in Jason's fixup] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 3 +++ drivers/net/wireless/ath/wcn36xx/smd.c | 27 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index d713204f755d..3af16cba3d12 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -54,6 +54,9 @@ /* Default Beacon template size */ #define BEACON_TEMPLATE_SIZE 0x180 +/* Minimum PVM size that the FW expects. See comment in smd.c for details. */ +#define TIM_MIN_PVM_SIZE 6 + /* Param Change Bitmap sent to HAL */ #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ff3ed2461a69..089a7e445cd6 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1375,12 +1375,19 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, u16 p2p_off) { struct wcn36xx_hal_send_beacon_req_msg msg_body; - int ret = 0; + int ret = 0, pad, pvm_len; mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); - msg_body.beacon_length = skb_beacon->len; + pvm_len = skb_beacon->data[tim_off + 1] - 3; + pad = TIM_MIN_PVM_SIZE - pvm_len; + + /* Padding is irrelevant to mesh mode since tim_off is always 0. */ + if (vif->type == NL80211_IFTYPE_MESH_POINT) + pad = 0; + + msg_body.beacon_length = skb_beacon->len + pad; /* TODO need to find out why + 6 is needed */ msg_body.beacon_length6 = msg_body.beacon_length + 6; @@ -1393,6 +1400,22 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len); memcpy(msg_body.bssid, vif->addr, ETH_ALEN); + if (pad > 0) { + /* + * The wcn36xx FW has a fixed size for the PVM in the TIM. If + * given the beacon template from mac80211 with a PVM shorter + * than the FW expectes it will overwrite the data after the + * TIM. + */ + wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n", + pad, pvm_len); + memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad], + &msg_body.beacon[tim_off + 5 + pvm_len], + skb_beacon->len - (tim_off + 5 + pvm_len)); + memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad); + msg_body.beacon[tim_off + 1] += pad; + } + /* TODO need to find out why this is needed? */ if (vif->type == NL80211_IFTYPE_MESH_POINT) /* mesh beacon don't need this, so push further down */ From ce75877f6c3da01cd5efe41683dd32beee1b4b33 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:41 -0700 Subject: [PATCH 112/164] wcn36xx: Add helper macros to cast vif to private vif and vice versa Makes the code a little easier to read. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/debug.c | 12 +++-------- drivers/net/wireless/ath/wcn36xx/main.c | 16 +++++++-------- drivers/net/wireless/ath/wcn36xx/pmc.c | 4 ++-- drivers/net/wireless/ath/wcn36xx/smd.c | 24 +++++++++------------- drivers/net/wireless/ath/wcn36xx/txrx.c | 8 ++------ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 12 +++++++++++ 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c index ef44a2da644d..2a6bb62e785c 100644 --- a/drivers/net/wireless/ath/wcn36xx/debug.c +++ b/drivers/net/wireless/ath/wcn36xx/debug.c @@ -33,9 +33,7 @@ static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, char buf[3]; list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) { if (vif_priv->pw_state == WCN36XX_BMPS) buf[0] = '1'; @@ -70,9 +68,7 @@ static ssize_t write_file_bool_bmps(struct file *file, case 'Y': case '1': list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) { wcn36xx_enable_keep_alive_null_packet(wcn, vif); wcn36xx_pmc_enter_bmps_state(wcn, vif); @@ -83,9 +79,7 @@ static ssize_t write_file_bool_bmps(struct file *file, case 'N': case '0': list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (NL80211_IFTYPE_STATION == vif->type) wcn36xx_pmc_exit_bmps_state(wcn, vif); } diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a27279c2c695..62cb9ffd854c 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -346,9 +346,7 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", ch); list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); wcn36xx_smd_switch_channel(wcn, vif, ch); } } @@ -387,7 +385,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = vif_priv->sta; int ret = 0; u8 key[WLAN_MAX_KEY_LEN]; @@ -590,7 +588,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; u16 tim_off, tim_len; enum wcn36xx_hal_link_state link_state; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", vif, changed); @@ -757,7 +755,7 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); list_del(&vif_priv->list); @@ -768,7 +766,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", vif, vif->type); @@ -792,7 +790,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", vif, sta->addr); @@ -817,7 +815,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c index 28b515c81b0e..589fe5f70971 100644 --- a/drivers/net/wireless/ath/wcn36xx/pmc.c +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c @@ -22,7 +22,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, struct ieee80211_vif *vif) { int ret = 0; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); /* TODO: Make sure the TX chain clean */ ret = wcn36xx_smd_enter_bmps(wcn, vif); if (!ret) { @@ -42,7 +42,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, struct ieee80211_vif *vif) { - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (WCN36XX_BMPS != vif_priv->pw_state) { wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 089a7e445cd6..cc1b3b7a4ff9 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -191,7 +191,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_sta *sta, struct wcn36xx_hal_config_sta_params *sta_params) { - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *priv_sta = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || @@ -726,7 +726,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, size_t len) { struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1175,7 +1175,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_bss_rsp_msg *rsp; struct wcn36xx_hal_config_bss_rsp_params *params; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1217,7 +1217,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct wcn36xx_hal_config_bss_req_msg msg; struct wcn36xx_hal_config_bss_params *bss; struct wcn36xx_hal_config_sta_params *sta_params; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1343,7 +1343,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_delete_bss_req_msg msg_body; - struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1633,7 +1633,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_enter_bmps_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1663,7 +1663,7 @@ int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_enter_bmps_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -1724,7 +1724,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, int packet_type) { struct wcn36xx_hal_keep_alive_req_msg msg_body; - struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); @@ -2027,9 +2027,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, list_for_each_entry(tmp, &wcn->vif_list, list) { wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", tmp->bss_index); - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); ieee80211_connection_loss(vif); } return 0; @@ -2044,9 +2042,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, if (tmp->bss_index == rsp->bss_index) { wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", rsp->bss_index); - vif = container_of((void *)tmp, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(tmp); ieee80211_connection_loss(vif); return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 99c21aac68bd..b12c89b5940a 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -102,9 +102,7 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, struct wcn36xx_vif *vif_priv = NULL; struct ieee80211_vif *vif = NULL; list_for_each_entry(vif_priv, &wcn->vif_list, list) { - vif = container_of((void *)vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(vif_priv); if (memcmp(vif->addr, addr, ETH_ALEN) == 0) return vif_priv; } @@ -167,9 +165,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, */ if (sta_priv) { __vif_priv = sta_priv->vif; - vif = container_of((void *)__vif_priv, - struct ieee80211_vif, - drv_priv); + vif = wcn36xx_priv_to_vif(__vif_priv); bd->dpu_sign = sta_priv->ucast_dpu_sign; if (vif->type == NL80211_IFTYPE_STATION) { diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 7b41e833e18c..c3ba07ed1db5 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -263,4 +263,16 @@ struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv) return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv); } +static inline +struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif) +{ + return (struct wcn36xx_vif *) vif->drv_priv; +} + +static inline +struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv) +{ + return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv); +} + #endif /* _WCN36XX_H_ */ From 657a49be13eda5a3befc161d1d499d413c348762 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:42 -0700 Subject: [PATCH 113/164] wcn36xx: Use consistent name for private vif Some code used priv_vif and some used vif_priv. Convert all to vif_priv for consistency. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index cc1b3b7a4ff9..170440ed5d85 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -191,7 +191,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_sta *sta, struct wcn36xx_hal_config_sta_params *sta_params) { - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *priv_sta = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || @@ -215,7 +215,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, else memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); - sta_params->encrypt_type = priv_vif->encrypt_type; + sta_params->encrypt_type = vif_priv->encrypt_type; sta_params->short_preamble_supported = true; sta_params->rifs_mode = 0; @@ -224,7 +224,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->uapsd = 0; sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; sta_params->max_ampdu_duration = 0; - sta_params->bssid_index = priv_vif->bss_index; + sta_params->bssid_index = vif_priv->bss_index; sta_params->p2p = 0; if (sta) { @@ -726,7 +726,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, size_t len) { struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -743,8 +743,8 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, "hal add sta self status %d self_sta_index %d dpu_index %d\n", rsp->status, rsp->self_sta_index, rsp->dpu_index); - priv_vif->self_sta_index = rsp->self_sta_index; - priv_vif->self_dpu_desc_index = rsp->dpu_index; + vif_priv->self_sta_index = rsp->self_sta_index; + vif_priv->self_dpu_desc_index = rsp->dpu_index; return 0; } @@ -1175,7 +1175,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_bss_rsp_msg *rsp; struct wcn36xx_hal_config_bss_rsp_params *params; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); if (len < sizeof(*rsp)) return -EINVAL; @@ -1198,14 +1198,14 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, params->bss_bcast_sta_idx, params->mac, params->tx_mgmt_power, params->ucast_dpu_signature); - priv_vif->bss_index = params->bss_index; + vif_priv->bss_index = params->bss_index; - if (priv_vif->sta) { - priv_vif->sta->bss_sta_index = params->bss_sta_index; - priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; + if (vif_priv->sta) { + vif_priv->sta->bss_sta_index = params->bss_sta_index; + vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index; } - priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature; + vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; return 0; } @@ -1343,13 +1343,13 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) { struct wcn36xx_hal_delete_bss_req_msg msg_body; - struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif); + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); - msg_body.bss_index = priv_vif->bss_index; + msg_body.bss_index = vif_priv->bss_index; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); From 90023c034fefe51cf67c719065434b0e43e9baf9 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:43 -0700 Subject: [PATCH 114/164] wcn36xx: Use define for invalid index and fix typo Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 2 +- drivers/net/wireless/ath/wcn36xx/main.c | 4 ++-- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 3af16cba3d12..433d9801a0ae 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -48,7 +48,7 @@ #define WCN36XX_HAL_IPV4_ADDR_LEN 4 -#define WALN_HAL_STA_INVALID_IDX 0xFF +#define WCN36XX_HAL_STA_INVALID_IDX 0xFF #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF /* Default Beacon template size */ diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 62cb9ffd854c..4781b5e8deb3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -618,7 +618,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, if (!is_zero_ether_addr(bss_conf->bssid)) { vif_priv->is_joining = true; - vif_priv->bss_index = 0xff; + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; wcn36xx_smd_join(wcn, bss_conf->bssid, vif->addr, WCN36XX_HW_CHANNEL(wcn)); wcn36xx_smd_config_bss(wcn, vif, NULL, @@ -711,7 +711,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->enable_beacon) { vif_priv->dtim_period = bss_conf->dtim_period; - vif_priv->bss_index = 0xff; + vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; wcn36xx_smd_config_bss(wcn, vif, NULL, vif->addr, false); skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 170440ed5d85..6d4aa9250ca8 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -197,7 +197,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { sta_params->type = 1; - sta_params->sta_index = 0xFF; + sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX; } else { sta_params->type = 0; sta_params->sta_index = 1; From a92e4696292199714d47d8e52c4bf0318324f77f Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:44 -0700 Subject: [PATCH 115/164] wcn36xx: Add helper macros to cast sta to priv While poking at this I also change two related things. I rename one variable to make the names consistent. I also move one assignment of priv_sta to the declaration to save a few lines. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 14 ++++++-------- drivers/net/wireless/ath/wcn36xx/smd.c | 12 ++++++------ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 6 ++++++ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 4781b5e8deb3..30f015d3a9e6 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -373,7 +373,7 @@ static void wcn36xx_tx(struct ieee80211_hw *hw, struct wcn36xx_sta *sta_priv = NULL; if (control->sta) - sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(control->sta); if (wcn36xx_start_tx(wcn, sta_priv, skb)) ieee80211_free_txskb(wcn->hw, skb); @@ -518,7 +518,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, { int i, size; u16 *rates_table; - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); u32 rates = sta->supp_rates[band]; memset(&sta_priv->supported_rates, 0, @@ -661,7 +661,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, rcu_read_unlock(); goto out; } - sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); @@ -791,7 +791,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", vif, sta->addr); @@ -816,7 +816,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", vif, sta->addr, sta_priv->sta_index); @@ -858,7 +858,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_ampdu_params *params) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_sta *sta_priv = NULL; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta); struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; @@ -867,8 +867,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); - sta_priv = (struct wcn36xx_sta *)sta->drv_priv; - switch (action) { case IEEE80211_AMPDU_RX_START: sta_priv->tid = tid; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 6d4aa9250ca8..ff56138528b6 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -192,7 +192,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct wcn36xx_hal_config_sta_params *sta_params) { struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *priv_sta = NULL; + struct wcn36xx_sta *sta_priv = NULL; if (vif->type == NL80211_IFTYPE_ADHOC || vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT) { @@ -228,17 +228,17 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->p2p = 0; if (sta) { - priv_sta = (struct wcn36xx_sta *)sta->drv_priv; + sta_priv = wcn36xx_sta_to_priv(sta); if (NL80211_IFTYPE_STATION == vif->type) memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); else memcpy(&sta_params->mac, sta->addr, ETH_ALEN); sta_params->wmm_enabled = sta->wme; sta_params->max_sp_len = sta->max_sp; - sta_params->aid = priv_sta->aid; + sta_params->aid = sta_priv->aid; wcn36xx_smd_set_sta_ht_params(sta, sta_params); - memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, - sizeof(priv_sta->supported_rates)); + memcpy(&sta_params->supported_rates, &sta_priv->supported_rates, + sizeof(sta_priv->supported_rates)); } else { wcn36xx_set_default_rates(&sta_params->supported_rates); wcn36xx_smd_set_sta_default_ht_params(sta_params); @@ -969,7 +969,7 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, { struct wcn36xx_hal_config_sta_rsp_msg *rsp; struct config_sta_rsp_params *params; - struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); if (len < sizeof(*rsp)) return -EINVAL; diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index c3ba07ed1db5..c368a34c8de7 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -275,4 +275,10 @@ struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv) return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv); } +static inline +struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta) +{ + return (struct wcn36xx_sta *)sta->drv_priv; +} + #endif /* _WCN36XX_H_ */ From 81c69263757788d77537fefdd9a55b05ed83c87b Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:45 -0700 Subject: [PATCH 116/164] wcn36xx: Fetch private sta data from sta entry instead of from vif For consistency with other code. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 30f015d3a9e6..a23738deb5b3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -386,7 +386,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct wcn36xx *wcn = hw->priv; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - struct wcn36xx_sta *sta_priv = vif_priv->sta; + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); int ret = 0; u8 key[WLAN_MAX_KEY_LEN]; From 25a44da26f2901308440a047b27a3a0054ea4a71 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:46 -0700 Subject: [PATCH 117/164] wcn36xx: Remove sta pointer in private vif struct This does not work with multiple sta's in a vif. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 3 --- drivers/net/wireless/ath/wcn36xx/smd.c | 28 ++++++++++++---------- drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 - 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index a23738deb5b3..7c06ca9fdd2c 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -796,7 +796,6 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, vif, sta->addr); spin_lock_init(&sta_priv->ampdu_lock); - vif_priv->sta = sta_priv; sta_priv->vif = vif_priv; /* * For STA mode HW will be configured on BSS_CHANGED_ASSOC because @@ -815,14 +814,12 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wcn36xx *wcn = hw->priv; - struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", vif, sta->addr, sta_priv->sta_index); wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); - vif_priv->sta = NULL; sta_priv->vif = NULL; return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ff56138528b6..76c6856ed932 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1170,6 +1170,7 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *buf, size_t len) { @@ -1200,9 +1201,10 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, vif_priv->bss_index = params->bss_index; - if (vif_priv->sta) { - vif_priv->sta->bss_sta_index = params->bss_sta_index; - vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index; + if (sta) { + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); + sta_priv->bss_sta_index = params->bss_sta_index; + sta_priv->bss_dpu_desc_index = params->dpu_desc_index; } vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; @@ -1329,6 +1331,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, } ret = wcn36xx_smd_config_bss_rsp(wcn, vif, + sta, wcn->hal_buf, wcn->hal_rsp_len); if (ret) { @@ -2058,25 +2061,24 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, { struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; struct wcn36xx_vif *tmp; - struct ieee80211_sta *sta = NULL; + struct ieee80211_sta *sta; if (len != sizeof(*rsp)) { wcn36xx_warn("Corrupted delete sta indication\n"); return -EIO; } + wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n", + rsp->addr2, rsp->sta_id); + list_for_each_entry(tmp, &wcn->vif_list, list) { - if (sta && (tmp->sta->sta_index == rsp->sta_id)) { - sta = container_of((void *)tmp->sta, - struct ieee80211_sta, - drv_priv); - wcn36xx_dbg(WCN36XX_DBG_HAL, - "delete station indication %pM index %d\n", - rsp->addr2, - rsp->sta_id); + rcu_read_lock(); + sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2); + if (sta) ieee80211_report_low_ack(sta, 0); + rcu_read_unlock(); + if (sta) return 0; - } } wcn36xx_warn("STA with addr %pM and index %d not found\n", diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index c368a34c8de7..54000db0af1a 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -125,7 +125,6 @@ struct wcn36xx_platform_ctrl_ops { */ struct wcn36xx_vif { struct list_head list; - struct wcn36xx_sta *sta; u8 dtim_period; enum ani_ed_type encrypt_type; bool is_joining; From 16be1ac55944412e8d132b1db26f994b368c5742 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:47 -0700 Subject: [PATCH 118/164] wcn36xx: Parse trigger_ba response properly This message does not follow the canonical format and needs it's own parser. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 76c6856ed932..7f315d098f52 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1968,6 +1968,17 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) return ret; } +static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len) +{ + struct wcn36xx_hal_trigger_ba_rsp_msg *rsp; + + if (len < sizeof(*rsp)) + return -EINVAL; + + rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf; + return rsp->status; +} + int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) { struct wcn36xx_hal_trigger_ba_req_msg msg_body; @@ -1992,8 +2003,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) wcn36xx_err("Sending hal_trigger_ba failed\n"); goto out; } - ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, - wcn->hal_rsp_len); + ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len); if (ret) { wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); goto out; From df98c3294bdf1fc3094f5466accf6423ce968a74 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:48 -0700 Subject: [PATCH 119/164] wcn36xx: Copy all members in config_sta v1 conversion When converting to version 1 of the config_sta struct not all members where copied. This fixes the problem of multicast frames not being delivered on an encrypted network. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 7f315d098f52..ebb446272d21 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -949,17 +949,32 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, memcpy(&v1->mac, orig->mac, ETH_ALEN); v1->aid = orig->aid; v1->type = orig->type; + v1->short_preamble_supported = orig->short_preamble_supported; v1->listen_interval = orig->listen_interval; + v1->wmm_enabled = orig->wmm_enabled; v1->ht_capable = orig->ht_capable; - + v1->tx_channel_width_set = orig->tx_channel_width_set; + v1->rifs_mode = orig->rifs_mode; + v1->lsig_txop_protection = orig->lsig_txop_protection; v1->max_ampdu_size = orig->max_ampdu_size; v1->max_ampdu_density = orig->max_ampdu_density; v1->sgi_40mhz = orig->sgi_40mhz; v1->sgi_20Mhz = orig->sgi_20Mhz; - + v1->rmf = orig->rmf; + v1->encrypt_type = orig->encrypt_type; + v1->action = orig->action; + v1->uapsd = orig->uapsd; + v1->max_sp_len = orig->max_sp_len; + v1->green_field_capable = orig->green_field_capable; + v1->mimo_ps = orig->mimo_ps; + v1->delayed_ba_support = orig->delayed_ba_support; + v1->max_ampdu_duration = orig->max_ampdu_duration; + v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz; memcpy(&v1->supported_rates, &orig->supported_rates, sizeof(orig->supported_rates)); v1->sta_index = orig->sta_index; + v1->bssid_index = orig->bssid_index; + v1->p2p = orig->p2p; } static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, From 6d9cf123cd79277c65605faff8d25dbdd1b6ca64 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:49 -0700 Subject: [PATCH 120/164] wcn36xx: Use allocated self sta index instead of hard coded Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ebb446272d21..e0d5631657c1 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -200,7 +200,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX; } else { sta_params->type = 0; - sta_params->sta_index = 1; + sta_params->sta_index = vif_priv->self_sta_index; } sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); From 2716a8ac655f17d17a7040f99f306a6244b08802 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:50 -0700 Subject: [PATCH 121/164] wcn36xx: Clear encrypt_type when deleting bss key This fixes a problem connecting to an open network after being connected to an encrypted network. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7c06ca9fdd2c..f9c77de94583 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -471,6 +471,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { + vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; wcn36xx_smd_remove_bsskey(wcn, vif_priv->encrypt_type, key_conf->keyidx); @@ -626,6 +627,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, } else { vif_priv->is_joining = false; wcn36xx_smd_delete_bss(wcn, vif); + vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; } } From 043ce546190243bd9de05dbb6c82c9099b01a3a2 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:51 -0700 Subject: [PATCH 122/164] wcn36xx: Track association state Knowing the association state is needed for mc filtering. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 ++ drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index f9c77de94583..253cece1b660 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -655,6 +655,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, vif->addr, bss_conf->aid); + vif_priv->sta_assoc = true; rcu_read_lock(); sta = ieee80211_find_sta(vif, bss_conf->bssid); if (!sta) { @@ -686,6 +687,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, bss_conf->bssid, vif->addr, bss_conf->aid); + vif_priv->sta_assoc = false; wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr, diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 54000db0af1a..7433d67a5929 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -128,6 +128,7 @@ struct wcn36xx_vif { u8 dtim_period; enum ani_ed_type encrypt_type; bool is_joining; + bool sta_assoc; struct wcn36xx_hal_mac_ssid ssid; /* Power management */ From 20a779ede344a0b9778b7d5d9af76453d14474fc Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:52 -0700 Subject: [PATCH 123/164] wcn36xx: Implement multicast filtering Pass the multicast list to FW. This patch also adds a way to build the smd command in place. This is needed because the MC list command is too big for the stack. Signed-off-by: Pontus Fuchs [bjorn: dropped FIF_PROMISC_IN_BSS usage] Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 6 +-- drivers/net/wireless/ath/wcn36xx/main.c | 50 ++++++++++++++++++++++-- drivers/net/wireless/ath/wcn36xx/smd.c | 51 +++++++++++++++++++++++++ drivers/net/wireless/ath/wcn36xx/smd.h | 3 ++ 4 files changed, 104 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 433d9801a0ae..ec64c47f918b 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -4267,9 +4267,9 @@ struct wcn36xx_hal_rcv_flt_mc_addr_list_type { u8 data_offset; u32 mc_addr_count; - u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; + u8 mc_addr[WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS][ETH_ALEN]; u8 bss_index; -}; +} __packed; struct wcn36xx_hal_set_pkt_filter_rsp_msg { struct wcn36xx_hal_msg_header header; @@ -4323,7 +4323,7 @@ struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { struct wcn36xx_hal_msg_header header; struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; -}; +} __packed; struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 253cece1b660..c0ba7b0775b3 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -287,6 +287,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw) } wcn36xx_detect_chip_version(wcn); + wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1); /* DMA channel initialization */ ret = wcn36xx_dxe_init(wcn); @@ -354,15 +355,57 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) return 0; } -#define WCN36XX_SUPPORTED_FILTERS (0) - static void wcn36xx_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total, u64 multicast) { + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; + struct wcn36xx *wcn = hw->priv; + struct wcn36xx_vif *tmp; + struct ieee80211_vif *vif = NULL; + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); - *total &= WCN36XX_SUPPORTED_FILTERS; + *total &= FIF_ALLMULTI; + + fp = (void *)(unsigned long)multicast; + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + + /* FW handles MC filtering only when connected as STA */ + if (*total & FIF_ALLMULTI) + wcn36xx_smd_set_mc_list(wcn, vif, NULL); + else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc) + wcn36xx_smd_set_mc_list(wcn, vif, fp); + } + kfree(fp); +} + +static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; + struct netdev_hw_addr *ha; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n"); + fp = kzalloc(sizeof(*fp), GFP_ATOMIC); + if (!fp) { + wcn36xx_err("Out of memory setting filters.\n"); + return 0; + } + + fp->mc_addr_count = 0; + /* update multicast filtering parameters */ + if (netdev_hw_addr_list_count(mc_list) <= + WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) { + netdev_hw_addr_list_for_each(ha, mc_list) { + memcpy(fp->mc_addr[fp->mc_addr_count], + ha->addr, ETH_ALEN); + fp->mc_addr_count++; + } + } + + return (u64)(unsigned long)fp; } static void wcn36xx_tx(struct ieee80211_hw *hw, @@ -920,6 +963,7 @@ static const struct ieee80211_ops wcn36xx_ops = { .resume = wcn36xx_resume, #endif .config = wcn36xx_config, + .prepare_multicast = wcn36xx_prepare_multicast, .configure_filter = wcn36xx_configure_filter, .tx = wcn36xx_tx, .set_key = wcn36xx_set_key, diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index e0d5631657c1..b1bdc229e560 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -271,6 +271,16 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) return ret; } +static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, + enum wcn36xx_hal_host_msg_type msg_type, + size_t msg_size) +{ + memset(hdr, 0, msg_size + sizeof(*hdr)); + hdr->msg_type = msg_type; + hdr->msg_version = WCN36XX_HAL_MSG_VERSION0; + hdr->len = msg_size + sizeof(*hdr); +} + #define INIT_HAL_MSG(msg_body, type) \ do { \ memset(&msg_body, 0, sizeof(msg_body)); \ @@ -2144,6 +2154,46 @@ int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) mutex_unlock(&wcn->hal_mutex); return ret; } + +int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp) +{ + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); + struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL; + int ret = 0; + + mutex_lock(&wcn->hal_mutex); + + msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *) + wcn->hal_buf; + init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ, + sizeof(msg_body->mc_addr_list)); + + /* An empty list means all mc traffic will be received */ + if (fp) + memcpy(&msg_body->mc_addr_list, fp, + sizeof(msg_body->mc_addr_list)); + else + msg_body->mc_addr_list.mc_addr_count = 0; + + msg_body->mc_addr_list.bss_index = vif_priv->bss_index; + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); + if (ret) { + wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n"); + goto out; + } + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); + if (ret) { + wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret); + goto out; + } +out: + mutex_unlock(&wcn->hal_mutex); + return ret; +} + static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) { struct wcn36xx_hal_msg_header *msg_header = buf; @@ -2185,6 +2235,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: case WCN36XX_HAL_CH_SWITCH_RSP: case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: + case WCN36XX_HAL_8023_MULTICAST_LIST_RSP: memcpy(wcn->hal_buf, buf, len); wcn->hal_rsp_len = len; complete(&wcn->hal_rsp_compl); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index 8361f9e3995b..c1b76d75cf85 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -136,4 +136,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); +int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp); #endif /* _SMD_H_ */ From 6770559b8f614d3569ced7a7e3a8e846115e77af Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 18 Apr 2016 22:00:53 -0700 Subject: [PATCH 124/164] wcn36xx: Use correct command struct for EXIT_BMPS_REQ EXIT_BMPS_REQ was using the command struct for ENTER_BMPS_REQ. I spotted this when looking at command dumps. Signed-off-by: Pontus Fuchs Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index b1bdc229e560..c15501c06eb2 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1690,7 +1690,7 @@ int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) { - struct wcn36xx_hal_enter_bmps_req_msg msg_body; + struct wcn36xx_hal_exit_bmps_req_msg msg_body; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); int ret = 0; From 5443918d050a1a1e5766544e3b895e98671adeef Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:54 -0700 Subject: [PATCH 125/164] wcn36xx: Delete BSS before idling link When disabling the beacon we must delete the bss before idling the link. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index c0ba7b0775b3..680217506b3d 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -779,9 +779,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, link_state); } else { + wcn36xx_smd_delete_bss(wcn, vif); wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, WCN36XX_HAL_LINK_IDLE_STATE); - wcn36xx_smd_delete_bss(wcn, vif); } } out: From 23c2aabb93c9c8efb7b8991707e2db59f7346783 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:55 -0700 Subject: [PATCH 126/164] wcn36xx: Correct remove bss key response encoding The WCN36XX_HAL_RMV_BSSKEY_RSP carries a single u32 with "status", so we can use the standard status check function for decoding the result. This is the last user of the v2 status checker, so remove the struct and helper function. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 19 +------------------ drivers/net/wireless/ath/wcn36xx/smd.h | 9 --------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index c15501c06eb2..5f6ca3124bd8 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -312,22 +312,6 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) return 0; } -static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf, - size_t len) -{ - struct wcn36xx_fw_msg_status_rsp_v2 *rsp; - - if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp)) - return wcn36xx_smd_rsp_status_check(buf, len); - - rsp = buf + sizeof(struct wcn36xx_hal_msg_header); - - if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) - return rsp->status; - - return 0; -} - int wcn36xx_smd_load_nv(struct wcn36xx *wcn) { struct nv_data *nv_d; @@ -1647,8 +1631,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, wcn36xx_err("Sending hal_remove_bsskey failed\n"); goto out; } - ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, - wcn->hal_rsp_len); + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); if (ret) { wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); goto out; diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index c1b76d75cf85..d74d781f4c8d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -44,15 +44,6 @@ struct wcn36xx_fw_msg_status_rsp { u32 status; } __packed; -/* wcn3620 returns this for tigger_ba */ - -struct wcn36xx_fw_msg_status_rsp_v2 { - u8 bss_id[6]; - u32 status __packed; - u16 count_following_candidates __packed; - /* candidate list follows */ -}; - struct wcn36xx_hal_ind_msg { struct list_head list; u8 *msg; From ffc03c331a1e7cafac3beb4f89c40fa7d6213d6e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 18 Apr 2016 22:00:56 -0700 Subject: [PATCH 127/164] wcn36xx: Fill in capability list Fill in the capability list with more values from the downstream driver. Signed-off-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/hal.h | 39 ++++++++++++++++++++++++ drivers/net/wireless/ath/wcn36xx/main.c | 40 ++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index ec64c47f918b..658bfb8baabe 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -4389,6 +4389,45 @@ enum place_holder_in_cap_bitmap { RTT = 20, RATECTRL = 21, WOW = 22, + WLAN_ROAM_SCAN_OFFLOAD = 23, + SPECULATIVE_PS_POLL = 24, + SCAN_SCH = 25, + IBSS_HEARTBEAT_OFFLOAD = 26, + WLAN_SCAN_OFFLOAD = 27, + WLAN_PERIODIC_TX_PTRN = 28, + ADVANCE_TDLS = 29, + BATCH_SCAN = 30, + FW_IN_TX_PATH = 31, + EXTENDED_NSOFFLOAD_SLOT = 32, + CH_SWITCH_V1 = 33, + HT40_OBSS_SCAN = 34, + UPDATE_CHANNEL_LIST = 35, + WLAN_MCADDR_FLT = 36, + WLAN_CH144 = 37, + NAN = 38, + TDLS_SCAN_COEXISTENCE = 39, + LINK_LAYER_STATS_MEAS = 40, + MU_MIMO = 41, + EXTENDED_SCAN = 42, + DYNAMIC_WMM_PS = 43, + MAC_SPOOFED_SCAN = 44, + BMU_ERROR_GENERIC_RECOVERY = 45, + DISA = 46, + FW_STATS = 47, + WPS_PRBRSP_TMPL = 48, + BCN_IE_FLT_DELTA = 49, + TDLS_OFF_CHANNEL = 51, + RTT3 = 52, + MGMT_FRAME_LOGGING = 53, + ENHANCED_TXBD_COMPLETION = 54, + LOGGING_ENHANCEMENT = 55, + EXT_SCAN_ENHANCED = 56, + MEMORY_DUMP_SUPPORTED = 57, + PER_PKT_STATS_SUPPORTED = 58, + EXT_LL_STAT = 60, + WIFI_CONFIG = 61, + ANTENNA_DIVERSITY_SELECTION = 62, + MAX_FEATURE_SUPPORTED = 128, }; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 680217506b3d..fe81b2a7c8d9 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -201,7 +201,45 @@ static const char * const wcn36xx_caps_names[] = { "BCN_FILTER", /* 19 */ "RTT", /* 20 */ "RATECTRL", /* 21 */ - "WOW" /* 22 */ + "WOW", /* 22 */ + "WLAN_ROAM_SCAN_OFFLOAD", /* 23 */ + "SPECULATIVE_PS_POLL", /* 24 */ + "SCAN_SCH", /* 25 */ + "IBSS_HEARTBEAT_OFFLOAD", /* 26 */ + "WLAN_SCAN_OFFLOAD", /* 27 */ + "WLAN_PERIODIC_TX_PTRN", /* 28 */ + "ADVANCE_TDLS", /* 29 */ + "BATCH_SCAN", /* 30 */ + "FW_IN_TX_PATH", /* 31 */ + "EXTENDED_NSOFFLOAD_SLOT", /* 32 */ + "CH_SWITCH_V1", /* 33 */ + "HT40_OBSS_SCAN", /* 34 */ + "UPDATE_CHANNEL_LIST", /* 35 */ + "WLAN_MCADDR_FLT", /* 36 */ + "WLAN_CH144", /* 37 */ + "NAN", /* 38 */ + "TDLS_SCAN_COEXISTENCE", /* 39 */ + "LINK_LAYER_STATS_MEAS", /* 40 */ + "MU_MIMO", /* 41 */ + "EXTENDED_SCAN", /* 42 */ + "DYNAMIC_WMM_PS", /* 43 */ + "MAC_SPOOFED_SCAN", /* 44 */ + "BMU_ERROR_GENERIC_RECOVERY", /* 45 */ + "DISA", /* 46 */ + "FW_STATS", /* 47 */ + "WPS_PRBRSP_TMPL", /* 48 */ + "BCN_IE_FLT_DELTA", /* 49 */ + "TDLS_OFF_CHANNEL", /* 51 */ + "RTT3", /* 52 */ + "MGMT_FRAME_LOGGING", /* 53 */ + "ENHANCED_TXBD_COMPLETION", /* 54 */ + "LOGGING_ENHANCEMENT", /* 55 */ + "EXT_SCAN_ENHANCED", /* 56 */ + "MEMORY_DUMP_SUPPORTED", /* 57 */ + "PER_PKT_STATS_SUPPORTED", /* 58 */ + "EXT_LL_STAT", /* 60 */ + "WIFI_CONFIG", /* 61 */ + "ANTENNA_DIVERSITY_SELECTION", /* 62 */ }; static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x) From e4c8b456c53d4beee5adaf5768c762171e2244f3 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 18 Mar 2016 13:27:09 +1100 Subject: [PATCH 128/164] rtl818x_pci: Fix a memory leak in rtl8180_init_rx_ring When dev_alloc_skb or pci_dma_mapping_error in rtl8180_init_rx_ring fails, the memory allocated by pci_zalloc_consistent is not freed. This patch fixes the bug by adding pci_free_consistent in error handling code. Signed-off-by: Jia-Ju Bai Signed-off-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index ba242d0160ec..e895a84481da 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -1018,6 +1018,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) dma_addr_t *mapping; entry = priv->rx_ring + priv->rx_ring_sz*i; if (!skb) { + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, + priv->rx_ring, priv->rx_ring_dma); wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); return -ENOMEM; } @@ -1028,6 +1030,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) if (pci_dma_mapping_error(priv->pdev, *mapping)) { kfree_skb(skb); + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, + priv->rx_ring, priv->rx_ring_dma); wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n"); return -ENOMEM; } From 706a527ca32b3bf950754631fa42982c0f1c060b Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Tue, 12 Apr 2016 23:09:16 -0700 Subject: [PATCH 129/164] prism54: isl_38xx: Replace 'struct timeval' 'struct timeval' uses a 32-bit seconds field which will overflow in year 2038 and beyond. This patch is part of a larger effort to remove all instances of 'struct timeval' from the kernel and replace them with 64-bit timekeeping variables. The patch also fixes the debug printf specifier to avoid the seconds value being truncated. The patch was build-tested / debugged by removing the "if VERBOSE > SHOW_ERROR_MESSAGES" guards. Signed-off-by: Tina Ruchandani Suggested-by: Arnd Bergmann Signed-off-by: Kalle Valo --- .../net/wireless/intersil/prism54/isl_38xx.c | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intersil/prism54/isl_38xx.c b/drivers/net/wireless/intersil/prism54/isl_38xx.c index 333c1a2f882e..6700387ef9ab 100644 --- a/drivers/net/wireless/intersil/prism54/isl_38xx.c +++ b/drivers/net/wireless/intersil/prism54/isl_38xx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -113,7 +114,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) #if VERBOSE > SHOW_ERROR_MESSAGES u32 counter = 0; - struct timeval current_time; + struct timespec64 current_ts64; DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); #endif @@ -121,22 +122,22 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) if (asleep) { /* device is in powersave, trigger the device for wakeup */ #if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", - current_time.tv_sec, (long)current_time.tv_usec); + ktime_get_real_ts64(¤t_ts64); + DEBUG(SHOW_TRACING, "%lld.%09ld Device wakeup triggered\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec); - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, + DEBUG(SHOW_TRACING, "%lld.%09ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, readl(device_base + ISL38XX_CTRL_STAT_REG)); #endif reg = readl(device_base + ISL38XX_INT_IDENT_REG); if (reg == 0xabadface) { #if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); + ktime_get_real_ts64(¤t_ts64); DEBUG(SHOW_TRACING, - "%08li.%08li Device register abadface\n", - current_time.tv_sec, (long)current_time.tv_usec); + "%lld.%09ld Device register abadface\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec); #endif /* read the Device Status Register until Sleepmode bit is set */ while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG), @@ -149,13 +150,13 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, - "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, + "%lld.%09ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, readl(device_base + ISL38XX_CTRL_STAT_REG)); - do_gettimeofday(¤t_time); + ktime_get_real_ts64(¤t_ts64); DEBUG(SHOW_TRACING, - "%08li.%08li Device asleep counter %i\n", - current_time.tv_sec, (long)current_time.tv_usec, + "%lld.%09ld Device asleep counter %i\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, counter); #endif } @@ -168,9 +169,9 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) /* perform another read on the Device Status Register */ reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, reg); + ktime_get_real_ts64(¤t_ts64); + DEBUG(SHOW_TRACING, "%lld.%00ld Device register read %08x\n", + (s64)current_ts64.tv_sec, current_ts64.tv_nsec, reg); #endif } else { /* device is (still) awake */ From 005a425b24e101d312eca669b96a6b71d75e97fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Fri, 15 Apr 2016 08:50:25 +0200 Subject: [PATCH 130/164] rtlwifi: rtl8821ae: Make sure loop counter is signed on all architectures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The for-loop condition does not work correctly on architectures where "char" is unsigned. Fix it by using an "int", which may also result in more efficient code. Signed-off-by: David Müller Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index ddf74d527017..0c3b9ce86e2e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -959,7 +959,7 @@ static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, u8 end, u8 base_val) { - char i = 0; + int i; u8 temp_value = 0; u32 temp_data = 0; From 7705ba6f7badb8cf38a0a19dad71e11a77ecb9cd Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Sun, 17 Apr 2016 16:44:58 +0200 Subject: [PATCH 131/164] brcmfmac: add support for nl80211 BSS_SELECT feature Announce support for nl80211 feature BSS_SELECT and process BSS selection behaviour provided in .connect() callback. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Lei Zhang Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 64 +++++++++++++++++++ .../broadcom/brcm80211/brcmfmac/common.c | 38 ++++++----- .../broadcom/brcm80211/brcmfmac/core.h | 1 + .../broadcom/brcm80211/brcmfmac/fwil.h | 1 + 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 8daad782b3c3..d0631b6cfd53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -250,6 +250,20 @@ struct parsed_vndr_ies { struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; }; +static u8 nl80211_band_to_fwil(enum nl80211_band band) +{ + switch (band) { + case NL80211_BAND_2GHZ: + return WLC_BAND_2G; + case NL80211_BAND_5GHZ: + return WLC_BAND_5G; + default: + WARN_ON(1); + break; + } + return 0; +} + static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, struct cfg80211_chan_def *ch) { @@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, return type; } +static void brcmf_set_join_pref(struct brcmf_if *ifp, + struct cfg80211_bss_selection *bss_select) +{ + struct brcmf_join_pref_params join_pref_params[2]; + enum nl80211_band band; + int err, i = 0; + + join_pref_params[i].len = 2; + join_pref_params[i].rssi_gain = 0; + + if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF) + brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO); + + switch (bss_select->behaviour) { + case __NL80211_BSS_SELECT_ATTR_INVALID: + brcmf_c_set_joinpref_default(ifp); + return; + case NL80211_BSS_SELECT_ATTR_BAND_PREF: + join_pref_params[i].type = BRCMF_JOIN_PREF_BAND; + band = bss_select->param.band_pref; + join_pref_params[i].band = nl80211_band_to_fwil(band); + i++; + break; + case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: + join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA; + band = bss_select->param.adjust.band; + join_pref_params[i].band = nl80211_band_to_fwil(band); + join_pref_params[i].rssi_gain = bss_select->param.adjust.delta; + i++; + break; + case NL80211_BSS_SELECT_ATTR_RSSI: + default: + break; + } + join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI; + join_pref_params[i].len = 2; + join_pref_params[i].rssi_gain = 0; + join_pref_params[i].band = 0; + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, + sizeof(join_pref_params)); + if (err) + brcmf_err("Set join_pref error (%d)\n", err); +} + static s32 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) @@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, ext_join_params->scan_le.nprobes = cpu_to_le32(-1); } + brcmf_set_join_pref(ifp, &sme->bss_select); + err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params, join_params_size); kfree(ext_join_params); @@ -6280,6 +6340,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites); if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) wiphy->n_cipher_suites--; + wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) | + BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) | + BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST); + wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 9e909e3c2f0c..3e15d64c6481 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -38,7 +38,7 @@ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 -/* boost value for RSSI_DELTA in preferred join selection */ +/* default boost value for RSSI_DELTA in preferred join selection */ #define BRCMF_JOIN_PREF_RSSI_BOOST 8 #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ @@ -83,11 +83,31 @@ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); static struct brcmfmac_platform_data *brcmfmac_pdata; struct brcmf_mp_global_t brcmf_mp_global; +void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) +{ + struct brcmf_join_pref_params join_pref_params[2]; + int err; + + /* Setup join_pref to select target by RSSI (boost on 5GHz) */ + join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; + join_pref_params[0].len = 2; + join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; + join_pref_params[0].band = WLC_BAND_5G; + + join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; + join_pref_params[1].len = 2; + join_pref_params[1].rssi_gain = 0; + join_pref_params[1].band = 0; + err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, + sizeof(join_pref_params)); + if (err) + brcmf_err("Set join_pref error (%d)\n", err); +} + int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; - struct brcmf_join_pref_params join_pref_params[2]; struct brcmf_rev_info_le revinfo; struct brcmf_rev_info *ri; char *ptr; @@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) goto done; } - /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ - join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; - join_pref_params[0].len = 2; - join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; - join_pref_params[0].band = WLC_BAND_5G; - join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; - join_pref_params[1].len = 2; - join_pref_params[1].rssi_gain = 0; - join_pref_params[1].band = 0; - err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, - sizeof(join_pref_params)); - if (err) - brcmf_err("Set join_pref error (%d)\n", err); + brcmf_c_set_joinpref_default(ifp); /* Setup event_msgs, enable E_IF */ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 241ee8d13e54..647d3cc2a4dc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -223,6 +223,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); +void brcmf_c_set_joinpref_default(struct brcmf_if *ifp); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 6b72df17744e..3a9a76dd9222 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -78,6 +78,7 @@ #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 +#define BRCMF_C_SET_ASSOC_PREFER 205 #define BRCMF_C_GET_VALID_CHANNELS 217 #define BRCMF_C_GET_KEY_PRIMARY 235 #define BRCMF_C_SET_KEY_PRIMARY 236 From 53985dccb1c98b7af080e2314bff0c5024e781b0 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Sun, 17 Apr 2016 15:25:03 +0200 Subject: [PATCH 132/164] brcmf: Fix null pointer exception in bcdc_hdrpull In fwsignal.c: brcmf_fws_commit_skb() ... if (rc < 0) { entry->transit_count--; if (entry->suppressed) entry->suppr_transit_count--; (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); ^^^^^^^ goto rollback; } ... The call to hdrpull will trigger a null pointer exception unless a null check is made in the method implementation. Signed-off-by: Per Forlin Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 288fe906c80e..d1bc51f92686 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -321,7 +321,8 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, if (pktbuf->len == 0) return -ENODATA; - *ifp = tmp_if; + if (ifp != NULL) + *ifp = tmp_if; return 0; } From 84039920bdff60030b2b79e50e4c9d230ae00dad Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 05:22:22 -0700 Subject: [PATCH 133/164] dt: bindings: add MARVELL's sd8xxx wireless device Add device tree binding documentation for MARVELL's sd8xxx (sd8897 and sd8997) wlan chip. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Acked-by: Rob Herring Signed-off-by: Kalle Valo --- .../bindings/net/wireless/marvell-sd8xxx.txt | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt diff --git a/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt b/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt new file mode 100644 index 000000000000..c421aba0a5bc --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt @@ -0,0 +1,63 @@ +Marvell 8897/8997 (sd8897/sd8997) SDIO devices +------ + +This node provides properties for controlling the marvell sdio wireless device. +The node is expected to be specified as a child node to the SDIO controller that +connects the device to the system. + +Required properties: + + - compatible : should be one of the following: + * "marvell,sd8897" + * "marvell,sd8997" + +Optional properties: + + - marvell,caldata* : A series of properties with marvell,caldata prefix, + represent calibration data downloaded to the device during + initialization. This is an array of unsigned 8-bit values. + the properties should follow below property name and + corresponding array length: + "marvell,caldata-txpwrlimit-2g" (length = 566). + "marvell,caldata-txpwrlimit-5g-sub0" (length = 502). + "marvell,caldata-txpwrlimit-5g-sub1" (length = 688). + "marvell,caldata-txpwrlimit-5g-sub2" (length = 750). + "marvell,caldata-txpwrlimit-5g-sub3" (length = 502). + - marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured + to firmware. Firmware will wakeup the host using this pin + during suspend/resume. + - interrupt-parent: phandle of the parent interrupt controller + - interrupts : interrupt pin number to the cpu. driver will request an irq based on + this interrupt number. during system suspend, the irq will be enabled + so that the wifi chip can wakeup host platform under certain condition. + during system resume, the irq will be disabled to make sure + unnecessary interrupt is not received. + +Example: + +Tx power limit calibration data is configured in below example. +The calibration data is an array of unsigned values, the length +can vary between hw versions. +IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured +so that firmware can wakeup host using this device side pin. + +&mmc3 { + status = "okay"; + vmmc-supply = <&wlan_en_reg>; + bus-width = <4>; + cap-power-off-card; + keep-power-in-suspend; + + #address-cells = <1>; + #size-cells = <0>; + mwifiex: wifi@1 { + compatible = "marvell,sd8897"; + reg = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + + marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 < + 0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>; + marvell,wakeup-pin = <3>; + }; +}; From ce4f6f0c353b7bfd7b527667287a87fd83aea119 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 05:22:23 -0700 Subject: [PATCH 134/164] mwifiex: add platform specific wakeup interrupt support On some arm-based platforms, we need to configure platform specific parameters by device tree node and also define our node as a child node of parent SDIO host controller. This patch parses these parameters from device tree. It includes calibration data dowoload to firmware, wakeup pin configured to firmware, and soc specific wake up gpio, which will be set as wakeup interrupt pin. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 11 +++ drivers/net/wireless/marvell/mwifiex/sdio.c | 77 +++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sdio.h | 7 ++ .../net/wireless/marvell/mwifiex/sta_cmd.c | 14 +++- 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 63069dd8b8e8..4c742a597cb0 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -37,6 +37,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "decl.h" #include "ioctl.h" diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index a0aec3e00457..cbd9dcd88b98 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -73,6 +73,66 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = { {"EXTLAST", NULL, 0, 0xFE}, }; +static const struct of_device_id mwifiex_sdio_of_match_table[] = { + { .compatible = "marvell,sd8897" }, + { .compatible = "marvell,sd8997" }, + { } +}; + +static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv) +{ + struct mwifiex_plt_wake_cfg *cfg = priv; + + if (cfg->irq_wifi >= 0) { + pr_info("%s: wake by wifi", __func__); + cfg->wake_by_wifi = true; + disable_irq_nosync(irq); + } + + return IRQ_HANDLED; +} + +/* This function parse device tree node using mmc subnode devicetree API. + * The device node is saved in card->plt_of_node. + * if the device tree node exist and include interrupts attributes, this + * function will also request platform specific wakeup interrupt. + */ +static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card) +{ + struct mwifiex_plt_wake_cfg *cfg; + int ret; + + if (!dev->of_node || + !of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) { + pr_err("sdio platform data not available"); + return -1; + } + + card->plt_of_node = dev->of_node; + card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg), + GFP_KERNEL); + cfg = card->plt_wake_cfg; + if (cfg && card->plt_of_node) { + cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0); + if (!cfg->irq_wifi) { + dev_err(dev, "fail to parse irq_wifi from device tree"); + } else { + ret = devm_request_irq(dev, cfg->irq_wifi, + mwifiex_wake_irq_wifi, + IRQF_TRIGGER_LOW, + "wifi_wake", cfg); + if (ret) { + dev_err(dev, + "Failed to request irq_wifi %d (%d)\n", + cfg->irq_wifi, ret); + } + disable_irq(cfg->irq_wifi); + } + } + + return 0; +} + /* * SDIO probe. * @@ -127,6 +187,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) return -EIO; } + /* device tree node parsing and platform specific configuration*/ + mwifiex_sdio_probe_of(&func->dev, card); + if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops, MWIFIEX_SDIO)) { pr_err("%s: add card failed\n", __func__); @@ -183,6 +246,13 @@ static int mwifiex_sdio_resume(struct device *dev) mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_SYNC_CMD); + /* Disable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) { + disable_irq_wake(card->plt_wake_cfg->irq_wifi); + if (!card->plt_wake_cfg->wake_by_wifi) + disable_irq(card->plt_wake_cfg->irq_wifi); + } + return 0; } @@ -262,6 +332,13 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; + /* Enable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) { + card->plt_wake_cfg->wake_by_wifi = false; + enable_irq(card->plt_wake_cfg->irq_wifi); + enable_irq_wake(card->plt_wake_cfg->irq_wifi); + } + /* Enable the Host Sleep */ if (!mwifiex_enable_hs(adapter)) { mwifiex_dbg(adapter, ERROR, diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index b9fbc5cf6262..db837f12c547 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -154,6 +154,11 @@ a->mpa_rx.start_port = 0; \ } while (0) +struct mwifiex_plt_wake_cfg { + int irq_wifi; + bool wake_by_wifi; +}; + /* data structure for SDIO MPA TX */ struct mwifiex_sdio_mpa_tx { /* multiport tx aggregation buffer pointer */ @@ -237,6 +242,8 @@ struct mwifiex_sdio_card_reg { struct sdio_mmc_card { struct sdio_func *func; struct mwifiex_adapter *adapter; + struct device_node *plt_of_node; + struct mwifiex_plt_wake_cfg *plt_wake_cfg; const char *firmware; const struct mwifiex_sdio_card_reg *reg; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 8cb895b7f2ee..e436574b1698 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -2162,6 +2162,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) enum state_11d_t state_11d; struct mwifiex_ds_11n_tx_cfg tx_cfg; u8 sdio_sp_rx_aggr_enable; + int data; if (first_sta) { if (priv->adapter->iface_type == MWIFIEX_PCIE) { @@ -2182,9 +2183,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) * The cal-data can be read from device tree and/or * a configuration file and downloaded to firmware. */ - adapter->dt_node = - of_find_node_by_name(NULL, "marvell_cfgdata"); - if (adapter->dt_node) { + if (priv->adapter->iface_type == MWIFIEX_SDIO && + adapter->dev->of_node) { + adapter->dt_node = adapter->dev->of_node; + if (of_property_read_u32(adapter->dt_node, + "marvell,wakeup-pin", + &data) == 0) { + pr_debug("Wakeup pin = 0x%x\n", data); + adapter->hs_cfg.gpio = data; + } + ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, "marvell,caldata"); if (ret) From eaf46b5fda3acd75df68f02d25754dccb446ec2d Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 18 Apr 2016 06:42:55 -0700 Subject: [PATCH 135/164] mwifiex: stop background scan when net device closed Transmit data path should not touch background scan. We will stop background scan when net device is closed. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index b459c70dc43f..8b67a552a690 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -702,6 +702,13 @@ mwifiex_close(struct net_device *dev) priv->scan_aborting = true; } + if (priv->sched_scanning) { + mwifiex_dbg(priv->adapter, INFO, + "aborting bgscan on ndo_stop\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + } + return 0; } @@ -753,13 +760,6 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) mwifiex_queue_main_work(priv->adapter); - if (priv->sched_scanning) { - mwifiex_dbg(priv->adapter, INFO, - "aborting bgscan on ndo_stop\n"); - mwifiex_stop_bg_scan(priv); - cfg80211_sched_scan_stopped(priv->wdev.wiphy); - } - return 0; } From a8c8dfa5931970a31794eeb65ced790fcff099d0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:21 -0400 Subject: [PATCH 136/164] rtl8xxxu: Rename rtl8723bu_update_rate_mask() to rtl8xxxu_gen2_update_rate_mask() Update the name of rtl8723bu_update_rate_mask() to make it reflect it's applicable for all/most gen2 N parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0ba84b5fe0d6..bea45095944f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8223,8 +8223,8 @@ static void rtl8723au_update_rate_mask(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.ramask)); } -static void rtl8723bu_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, int sgi) +static void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) { struct h2c_cmd h2c; u8 bw = 0; @@ -9925,7 +9925,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, - .update_rate_mask = rtl8723bu_update_rate_mask, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, @@ -9996,7 +9996,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .disable_rf = rtl8723b_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, - .update_rate_mask = rtl8723bu_update_rate_mask, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8723bu_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, From 32353a784f431185690919049b6951d309dc186e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:22 -0400 Subject: [PATCH 137/164] rtl8xxxu: Rename rtl8723bu_report_connect() to rtl8xxxu_gen2_report_connect() Make the name reflect this is for most/all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index bea45095944f..4af0c33b71bd 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8266,8 +8266,8 @@ static void rtl8723au_report_connect(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.joinbss)); } -static void rtl8723bu_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) +static void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, + u8 macid, bool connect) { struct h2c_cmd h2c; @@ -9926,7 +9926,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, - .report_connect = rtl8723bu_report_connect, + .report_connect = rtl8xxxu_gen2_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, @@ -9997,7 +9997,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, - .report_connect = rtl8723bu_report_connect, + .report_connect = rtl8xxxu_gen2_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT0_8723B, .mbox_ext_width = 4, From beb5531619c615f9b1d204d6d300dfe9e2fd454e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:23 -0400 Subject: [PATCH 138/164] rtl8xxxu: Rename rtl8723au_report_connect() to rtl8xxxu_gen1_report_connect() Rename the function to reflect it is for all/most gen1 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 4af0c33b71bd..882fa12266f9 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8249,8 +8249,8 @@ static void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.b_macid_cfg)); } -static void rtl8723au_report_connect(struct rtl8xxxu_priv *priv, - u8 macid, bool connect) +static void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, + u8 macid, bool connect) { struct h2c_cmd h2c; @@ -9890,7 +9890,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, - .report_connect = rtl8723au_report_connect, + .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, @@ -9962,7 +9962,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, - .report_connect = rtl8723au_report_connect, + .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT_0, .mbox_ext_width = 2, From 3a56bf6aa13c1bb6e4012824e0897f32acbb1f04 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:24 -0400 Subject: [PATCH 139/164] rtl8xxxu: Rename rtl8723bu_config_channel() to rtl8xxxu_gen2_config_channel() Rename the function to indicate it is applicable to most/all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 882fa12266f9..88e8fe92688f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2345,7 +2345,7 @@ static void rtl8723au_config_channel(struct ieee80211_hw *hw) } } -static void rtl8723bu_config_channel(struct ieee80211_hw *hw) +static void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; u32 val32, rsr; @@ -9917,7 +9917,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_phy_rf = rtl8723bu_init_phy_rf, .phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection, .phy_iq_calibrate = rtl8723bu_phy_iq_calibrate, - .config_channel = rtl8723bu_config_channel, + .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, @@ -9990,7 +9990,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .init_phy_bb = rtl8192eu_init_phy_bb, .init_phy_rf = rtl8192eu_init_phy_rf, .phy_iq_calibrate = rtl8192eu_phy_iq_calibrate, - .config_channel = rtl8723bu_config_channel, + .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8192e_enable_rf, .disable_rf = rtl8723b_disable_rf, From 6a07b7915afe876195f8c8715ebc438c0b1d1348 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:25 -0400 Subject: [PATCH 140/164] rtl8xxxu: Rename rtl8723b_disable_rf() to rtl8xxxu_gen2_disable_rf() At least for now, all gen2 parts use the same disable_rf() function Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 88e8fe92688f..3499f9b2b9f6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -7663,7 +7663,7 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.ignore_wlan)); } -static void rtl8723b_disable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv) { u32 val32; @@ -9922,7 +9922,7 @@ static struct rtl8xxxu_fileops rtl8723bu_fops = { .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, .enable_rf = rtl8723b_enable_rf, - .disable_rf = rtl8723b_disable_rf, + .disable_rf = rtl8xxxu_gen2_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8723b_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, @@ -9993,7 +9993,7 @@ static struct rtl8xxxu_fileops rtl8192eu_fops = { .config_channel = rtl8xxxu_gen2_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .enable_rf = rtl8192e_enable_rf, - .disable_rf = rtl8723b_disable_rf, + .disable_rf = rtl8xxxu_gen2_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, .set_tx_power = rtl8192e_set_tx_power, .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, From 7eb1400c247934dc485817a2c2b62540121a6e55 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:26 -0400 Subject: [PATCH 141/164] rtl8xxxu: Rename rtl8723a_disable_rf() to rtl8xxxu_gen1_disable_rf() All currently supported gen1 parts use the same disable_rf() routine, so rename the function to reflect that. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 3499f9b2b9f6..0d2beef089ff 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2124,7 +2124,7 @@ static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); } -static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_disable_rf(struct rtl8xxxu_priv *priv) { u8 sps0; u32 val32; @@ -9886,7 +9886,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, - .disable_rf = rtl8723a_disable_rf, + .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, @@ -9958,7 +9958,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .config_channel = rtl8723au_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, - .disable_rf = rtl8723a_disable_rf, + .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, .update_rate_mask = rtl8723au_update_rate_mask, From e09718c2fddfc68a14503ea2016970e48872e722 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:27 -0400 Subject: [PATCH 142/164] rtl8xxxu: Rename rtl8723au_config_channel() to rtl8xxxu_gen1_config_channel() All supported gen1 parts use the same config_channel() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 0d2beef089ff..e7f8039abe80 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2223,7 +2223,7 @@ static int rtl8723b_channel_to_group(int channel) return group; } -static void rtl8723au_config_channel(struct ieee80211_hw *hw) +static void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; u32 val32, rsr; @@ -9883,7 +9883,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, - .config_channel = rtl8723au_config_channel, + .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, @@ -9955,7 +9955,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, - .config_channel = rtl8723au_config_channel, + .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, From c6e39da02e17bf3521f1c08df1555b6ffa77dee4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:28 -0400 Subject: [PATCH 143/164] rtl8xxxu: Rename rtl8723au_update_rate_mask() to rtl8xxxu_update_rate_mask() All currently supported gen1 parts use the same function for updating the rate mask, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index e7f8039abe80..c6d5d7267954 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -8203,8 +8203,8 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); } -static void rtl8723au_update_rate_mask(struct rtl8xxxu_priv *priv, - u32 ramask, int sgi) +static void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) { struct h2c_cmd h2c; @@ -9889,7 +9889,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, - .update_rate_mask = rtl8723au_update_rate_mask, + .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, .mbox_ext_reg = REG_HMBOX_EXT_0, @@ -9961,7 +9961,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8723a_set_tx_power, - .update_rate_mask = rtl8723au_update_rate_mask, + .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, .mbox_ext_reg = REG_HMBOX_EXT_0, From 28466e9214029ef0978acfbaae0f02f78caa4ae9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:29 -0400 Subject: [PATCH 144/164] rtl8xxxu: Rename rtl8723au_phy_iq_calibrate() to rtl8xxxu_gen1_phy_iq_calibrate() All supported gen1 parts use the same phy_iq_calibrate() function (unlike their gen2 counterparts). Rename the function to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index c6d5d7267954..31918475cd85 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -6107,7 +6107,7 @@ static void rtl8xxxu_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.bt_wlan_calibration)); } -static void rtl8723au_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv) { struct device *dev = &priv->udev->dev; int result[4][8]; /* last is final result */ @@ -9882,7 +9882,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, - .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, + .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, @@ -9954,7 +9954,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .llt_init = rtl8xxxu_init_llt_table, .init_phy_bb = rtl8723au_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, - .phy_iq_calibrate = rtl8723au_phy_iq_calibrate, + .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, .enable_rf = rtl8723a_enable_rf, From de7c189c342da635d8b17460b851fbe9b7f1e898 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:30 -0400 Subject: [PATCH 145/164] rtl8xxxu: Rename rtl8723au_init_phy_bb() to rtl8xxxu_gen1_init_phy_bb() All gen1 parts use the same init_phy_bb() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 31918475cd85..a0b9bd9cbad1 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -3814,7 +3814,7 @@ static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, return 0; } -static void rtl8723au_init_phy_bb(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv) { u8 val8, ldoa15, ldov12d, lpldo, ldohci12; u16 val16; @@ -9880,7 +9880,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, - .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_bb = rtl8xxxu_gen1_init_phy_bb, .init_phy_rf = rtl8723au_init_phy_rf, .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, @@ -9952,7 +9952,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .power_off = rtl8xxxu_power_off, .reset_8051 = rtl8xxxu_reset_8051, .llt_init = rtl8xxxu_init_llt_table, - .init_phy_bb = rtl8723au_init_phy_bb, + .init_phy_bb = rtl8xxxu_gen1_init_phy_bb, .init_phy_rf = rtl8192cu_init_phy_rf, .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, From 42a3bc7a2a8525f9a3679e5dad19866ef34e2c09 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:31 -0400 Subject: [PATCH 146/164] rtl8xxxu: Rename rtl8723a_set_tx_power() to rtl8xxxu_gen1_set_tx_power() All gen1 parts use the same interface for setting TX power, so rename the function to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index a0b9bd9cbad1..843d4eac0d5a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2476,7 +2476,7 @@ static void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) } static void -rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) { struct rtl8xxxu_power_base *power_base = priv->power_base; u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; @@ -9888,7 +9888,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, - .set_tx_power = rtl8723a_set_tx_power, + .set_tx_power = rtl8xxxu_gen1_set_tx_power, .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 1024, @@ -9960,7 +9960,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .enable_rf = rtl8723a_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, - .set_tx_power = rtl8723a_set_tx_power, + .set_tx_power = rtl8xxxu_gen1_set_tx_power, .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .writeN_block_size = 128, From 8396a41cf7478f950f4682c1333771e1e4cf0b36 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:32 -0400 Subject: [PATCH 147/164] rtl8xxxu: Rename rtl8723a_enable_rf() to rtl8xxxu_gen1_enable_rf() All gen1 parts use the same enable_rf() function, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 843d4eac0d5a..7ed685cc3cbb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2080,7 +2080,7 @@ static void rtl8723bu_write_btreg(struct rtl8xxxu_priv *priv, u8 reg, u8 data) rtl8723a_h2c_cmd(priv, &h2c, sizeof(h2c.bt_mp_oper)); } -static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) +static void rtl8xxxu_gen1_enable_rf(struct rtl8xxxu_priv *priv) { u8 val8; u32 val32; @@ -9885,7 +9885,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, - .enable_rf = rtl8723a_enable_rf, + .enable_rf = rtl8xxxu_gen1_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8xxxu_gen1_set_tx_power, @@ -9957,7 +9957,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate, .config_channel = rtl8xxxu_gen1_config_channel, .parse_rx_desc = rtl8xxxu_parse_rxdesc16, - .enable_rf = rtl8723a_enable_rf, + .enable_rf = rtl8xxxu_gen1_enable_rf, .disable_rf = rtl8xxxu_gen1_disable_rf, .usb_quirks = rtl8xxxu_gen1_usb_quirks, .set_tx_power = rtl8xxxu_gen1_set_tx_power, From 8db71451e5c4ab5813e70b22a876e67a29a57a3f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:33 -0400 Subject: [PATCH 148/164] rtl8xxxu: Rename rtl8723a_mac_init_table to rtl8xxxu_gen1_mac_init_table All currently supported gen1 parts use the same mac_init_table, so rename it to reflect this. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7ed685cc3cbb..84c4bc65117b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -128,7 +128,7 @@ static struct ieee80211_supported_band rtl8xxxu_supported_band = { .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates), }; -static struct rtl8xxxu_reg8val rtl8723a_mac_init_table[] = { +static struct rtl8xxxu_reg8val rtl8xxxu_gen1_mac_init_table[] = { {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00}, @@ -9903,7 +9903,7 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .trxff_boundary = 0x27ff, .pbp_rx = PBP_PAGE_SIZE_128, .pbp_tx = PBP_PAGE_SIZE_128, - .mactable = rtl8723a_mac_init_table, + .mactable = rtl8xxxu_gen1_mac_init_table, }; static struct rtl8xxxu_fileops rtl8723bu_fops = { @@ -9975,7 +9975,7 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .trxff_boundary = 0x27ff, .pbp_rx = PBP_PAGE_SIZE_128, .pbp_tx = PBP_PAGE_SIZE_128, - .mactable = rtl8723a_mac_init_table, + .mactable = rtl8xxxu_gen1_mac_init_table, }; #endif From 5ac74145487dbf93a109a06c8aec0da1395c35f5 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:34 -0400 Subject: [PATCH 149/164] rtl8xxxu: Rename rtl8723b_channel_to_group() This renames rtl8723b_channel_to_group() to rtl8xxxu_gen2_channel_to_group() to reflect it is used by all currently supported gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 84c4bc65117b..1f517d0bb4bb 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -2205,7 +2205,7 @@ static int rtl8723a_channel_to_group(int channel) /* * Valid for rtl8723bu and rtl8192eu */ -static int rtl8723b_channel_to_group(int channel) +static int rtl8xxxu_gen2_channel_to_group(int channel) { int group; @@ -2617,7 +2617,7 @@ rtl8723b_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) int group, tx_idx; tx_idx = 0; - group = rtl8723b_channel_to_group(channel); + group = rtl8xxxu_gen2_channel_to_group(channel); cck = priv->cck_tx_power_index_B[group]; val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); @@ -2656,7 +2656,7 @@ rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) int group, tx_idx; tx_idx = 0; - group = rtl8723b_channel_to_group(channel); + group = rtl8xxxu_gen2_channel_to_group(channel); cck = priv->cck_tx_power_index_A[group]; From 85f466350abf3a7eeb579a3abd75f85e36d591fa Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:35 -0400 Subject: [PATCH 150/164] rtl8xxxu: Rename rtl8723bu_simularity_compare() This renames rtl8723bu_simularity_compare() to rtl8xxxu_gen2_simularity_compare() to reflect it is used for all gen2 parts. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 1f517d0bb4bb..7d4645588ab9 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -4595,8 +4595,8 @@ static bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv, return false; } -static bool rtl8723bu_simularity_compare(struct rtl8xxxu_priv *priv, - int result[][8], int c1, int c2) +static bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, + int result[][8], int c1, int c2) { u32 i, j, diff, simubitmap, bound = 0; int candidate[2] = {-1, -1}; /* for path A and path B */ @@ -6237,7 +6237,8 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8723bu_phy_iqcalibrate(priv, result, i); if (i == 1) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 1); if (simu) { candidate = 0; break; @@ -6245,13 +6246,15 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) } if (i == 2) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 2); if (simu) { candidate = 0; break; } - simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 1, 2); if (simu) { candidate = 1; } else { @@ -6352,7 +6355,8 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8192eu_phy_iqcalibrate(priv, result, i); if (i == 1) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 1); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 1); if (simu) { candidate = 0; break; @@ -6360,13 +6364,15 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) } if (i == 2) { - simu = rtl8723bu_simularity_compare(priv, result, 0, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 0, 2); if (simu) { candidate = 0; break; } - simu = rtl8723bu_simularity_compare(priv, result, 1, 2); + simu = rtl8xxxu_gen2_simularity_compare(priv, + result, 1, 2); if (simu) candidate = 1; else From 04a74a9f8af0cd61598e886c260ad0644b1dd5c0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 18 Apr 2016 11:49:36 -0400 Subject: [PATCH 151/164] rtl8xxxu: Rename rtl8723au_iqk_phy_iq_bb_reg There is nothing 8723au specific about rtl8723au_iqk_phy_iq_bb_reg so rename the array to rtl8xxxu_iqk_phy_iq_bb_reg. Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7d4645588ab9..f2ce8c9a31cf 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1747,7 +1747,7 @@ static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { }, }; -static const u32 rtl8723au_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { +static const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { REG_OFDM0_XA_RX_IQ_IMBALANCE, REG_OFDM0_XB_RX_IQ_IMBALANCE, REG_OFDM0_ENERGY_CCA_THRES, @@ -6205,7 +6205,7 @@ static void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); rtl8xxxu_prepare_calibrate(priv, 0); @@ -6313,7 +6313,7 @@ static void rtl8723bu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); rtl8xxxu_write32(priv, REG_BT_CONTROL_8723BU, bt_control); @@ -6424,7 +6424,7 @@ static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, candidate, (reg_ec4 == 0)); - rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg, priv->bb_recovery_backup, RTL8XXXU_BB_REGS); } From e0bdef0f75f0ee0d4747b72fa75310da78dbfa56 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:21:58 -0700 Subject: [PATCH 152/164] mwifiex: missing error code on allocation failure We accidentally return success instead of -ENOMEM. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index 05108618430d..cdd8f9a867a9 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -1017,8 +1017,10 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, /* Allocate memory for receive */ recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL); - if (!recv_buff) + if (!recv_buff) { + ret = -ENOMEM; goto cleanup; + } do { /* Send pseudo data to check winner status first */ From 394f0ed53108d5e038910e3eb733ccd3f0d9c464 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:23:44 -0700 Subject: [PATCH 153/164] mwifiex: fix loop timeout in mwifiex_prog_fw_w_helper() USB8XXX_FW_MAX_RETRY is 3. We were using a post-op loop "while (retries--) {" but then the lines after that assume the loop exits with retries set to zero. I've fixed this by changing to a pre-op loop. I started with retries set to 4 instead of 3 so that we still go through the loop the same number of times. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/usb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index cdd8f9a867a9..0857575c5c39 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -995,7 +995,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, { int ret = 0; u8 *firmware = fw->fw_buf, *recv_buff; - u32 retries = USB8XXX_FW_MAX_RETRY, dlen; + u32 retries = USB8XXX_FW_MAX_RETRY + 1; + u32 dlen; u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0; struct fw_data *fwdata; struct fw_sync_header sync_fw; @@ -1043,7 +1044,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, } /* If the send/receive fails or CRC occurs then retry */ - while (retries--) { + while (--retries) { u8 *buf = (u8 *)fwdata; u32 len = FW_DATA_XMIT_SIZE; @@ -1103,7 +1104,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, continue; } - retries = USB8XXX_FW_MAX_RETRY; + retries = USB8XXX_FW_MAX_RETRY + 1; break; } fw_seqnum++; From 81542fac6eae586e0d6fd502618342e8e20b4c5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Apr 2016 07:25:43 -0700 Subject: [PATCH 154/164] brcmfmac: testing the wrong variable in brcmf_rx_hdrpull() Smatch complains about this code: drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:335 brcmf_rx_hdrpull() error: we previously assumed '*ifp' could be null (see line 333) The problem is that we recently changed these from "ifp" to "*ifp" but there was one that we didn't update. - if (ret || !ifp || !ifp->ndev) { + if (ret || !(*ifp) || !(*ifp)->ndev) { if (ret != -ENODATA && ifp) ^^^ - ifp->stats.rx_errors++; + (*ifp)->stats.rx_errors++; I have updated it to *ifp as well. We always call this function is a non-NULL "ifp" pointer, btw. Fixes: c462ebcdfe42 ('brcmfmac: create common function for handling brcmf_proto_hdrpull()') Signed-off-by: Dan Carpenter Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 1b476d1fec2c..b590499f6883 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -331,7 +331,7 @@ static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, ret = brcmf_proto_hdrpull(drvr, true, skb, ifp); if (ret || !(*ifp) || !(*ifp)->ndev) { - if (ret != -ENODATA && ifp) + if (ret != -ENODATA && *ifp) (*ifp)->stats.rx_errors++; brcmu_pkt_buf_free_skb(skb); return -ENODATA; From 2557654df14b95141f1410127c33ed1661a8abbb Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Thu, 21 Apr 2016 00:41:34 +0800 Subject: [PATCH 155/164] rt2800lib: enable MFP if hw crypt is disabled If rt2800usb is loaded with nohwcrypt=1, mac80211 takes care of the crypto with software encryption/decryption and thus, MFP can be used. Tested for secured mesh using ath9k_htc and ath9k. Signed-off-by: Chun-Yeow Yeoh Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index c36fa4e03fb6..bf3f0a39908c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -7492,6 +7492,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) if (!rt2x00_is_usb(rt2x00dev)) ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING); + /* Set MFP if HW crypto is disabled. */ + if (rt2800_hwcrypt_disabled(rt2x00dev)) + ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE); + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2800_eeprom_addr(rt2x00dev, From f0d8f38cd909e072833a06b79939256c4aebe3a0 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 25 Apr 2016 20:02:09 +0300 Subject: [PATCH 156/164] iwlwifi: fix fw version reading for DVM devices In commit 97f95c93c8ed ("iwlwifi: remove support for fw older than -16.ucode") we accidentally changed the fw version reading code for DVM devices. The code intended to remove the old fw version API, because all MVM firmwares version 16 and above that we support don't use it anymore. But DVM devices still use the old FW API. Fix that by bringing the code back in. Reported-by: Pat Erley Tested-by: Kalle Valo Fixes: 97f95c93c8ed ("iwlwifi: remove support for fw older than-16.ucode") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 48e873732d4e..4f495d9153a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1280,7 +1280,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) if (err) goto try_again; - api_ver = drv->fw.ucode_ver; + if (fw_has_api(&drv->fw.ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION)) + api_ver = drv->fw.ucode_ver; + else + api_ver = IWL_UCODE_API(drv->fw.ucode_ver); /* * api_ver should match the api version forming part of the diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 843232bd8bbe..37dc09e8b6a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -251,6 +251,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params + * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority * instead of 3. * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size @@ -263,6 +264,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, + IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, From bb28c28ee10559c5bc5b5f48c2d6f6f2f6bd5586 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:19:35 -0400 Subject: [PATCH 157/164] mwifiex: bridged packets cause wmm_tx_pending counter to go negative When a packet is queued from the bridge, wmm_tx_pending is not incremented, but when the packet is dequeued the counter is decremented. Signed-off-by: Marty Faltesek Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index c95b61dc87c2..666e91af59d7 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -102,6 +102,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, int hdr_chop; struct ethhdr *p_ethhdr; struct mwifiex_sta_node *src_node; + int index; uap_rx_pd = (struct uap_rxpd *)(skb->data); rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); @@ -208,6 +209,9 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, } __net_timestamp(skb); + + index = mwifiex_1d_to_wmm_queue[skb->priority]; + atomic_inc(&priv->wmm_tx_pending[index]); mwifiex_wmm_add_buf_txqueue(priv, skb); atomic_inc(&adapter->tx_pending); atomic_inc(&adapter->pending_bridged_pkts); From b977d305ad20e05212c0ded2a7ef90e411edc1b3 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:20:52 -0400 Subject: [PATCH 158/164] mwifiex: fw download does not release sdio bus during failure Signed-off-by: Marty Faltesek Reviewed-by: Julian Calaby Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sdio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index cbd9dcd88b98..099722e1f867 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1103,13 +1103,12 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, offset += txlen; } while (true); - sdio_release_host(card->func); - mwifiex_dbg(adapter, MSG, "info: FW download over, size %d bytes\n", offset); ret = 0; done: + sdio_release_host(card->func); kfree(fwbuf); return ret; } From 8d666302df95ab585f5cc7b2fb779991f8797eb5 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Wed, 20 Apr 2016 00:22:01 -0400 Subject: [PATCH 159/164] mwifiex: transmit packet stats incorrect. tx_packets counter is incremented for aggregated packets, when it had already been incremented for the aggregated packet's constituent parts. Removing the extra count. Signed-off-by: Marty Faltesek Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/txrx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c index bf6182b646a5..abdd0cf710bf 100644 --- a/drivers/net/wireless/marvell/mwifiex/txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/txrx.c @@ -297,6 +297,13 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, goto done; mwifiex_set_trans_start(priv->netdev); + + if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) + atomic_dec_return(&adapter->pending_bridged_pkts); + + if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) + goto done; + if (!status) { priv->stats.tx_packets++; priv->stats.tx_bytes += tx_info->pkt_len; @@ -306,12 +313,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, priv->stats.tx_errors++; } - if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) - atomic_dec_return(&adapter->pending_bridged_pkts); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) - goto done; - if (aggr) /* For skb_aggr, do not wake up tx queue */ goto done; From 3f210e2f1269ffe83188db2f1f5839da907fc722 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:54 -0700 Subject: [PATCH 160/164] mwifiex: fix coding style Redundant space in case statement is removed. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 6db202fa7157..369ea06eca52 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3388,7 +3388,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) break; case CONTROL_FRAME_MATCHED: break; - case MANAGEMENT_FRAME_MATCHED: + case MANAGEMENT_FRAME_MATCHED: break; case GTK_REKEY_FAILURE: if (wiphy->wowlan_config->gtk_rekey_failure) From df2288623ee0ce77743d76ed8ca816e92246e77b Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:55 -0700 Subject: [PATCH 161/164] mwifiex: report wowlan wakeup reasons correctly It's been observed that wakeup on GTK rekey failure wasn't reported to cfg80211. This patch corrects the check so that all valid wakeup reasons are reported. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 369ea06eca52..734cf67b79c1 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3344,6 +3344,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) struct mwifiex_ds_wakeup_reason wakeup_reason; struct cfg80211_wowlan_wakeup wakeup_report; int i; + bool report_wakeup_reason = true; for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; @@ -3386,20 +3387,16 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) if (wiphy->wowlan_config->n_patterns) wakeup_report.pattern_idx = 1; break; - case CONTROL_FRAME_MATCHED: - break; - case MANAGEMENT_FRAME_MATCHED: - break; case GTK_REKEY_FAILURE: if (wiphy->wowlan_config->gtk_rekey_failure) wakeup_report.gtk_rekey_failure = true; break; default: + report_wakeup_reason = false; break; } - if ((wakeup_reason.hs_wakeup_reason > 0) && - (wakeup_reason.hs_wakeup_reason <= 7)) + if (report_wakeup_reason) cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, GFP_KERNEL); From d286af9bf40ab88f2035aef293f6ecae4187c6bb Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 21 Apr 2016 08:07:56 -0700 Subject: [PATCH 162/164] mwifiex: avoid querying wakeup reason when wowlan is disabled In cfg80211 resume handler, we query wakeup reason from firmware and report to cfg80211. if wowlan is disabled, connection is already terminated during suspend. We don't need to query wakeup reason in this case. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 734cf67b79c1..ff948a922222 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3355,6 +3355,9 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) } } + if (!wiphy->wowlan_config) + goto done; + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, &wakeup_reason); @@ -3400,6 +3403,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy) cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, GFP_KERNEL); +done: if (adapter->nd_info) { for (i = 0 ; i < adapter->nd_info->n_matches ; i++) kfree(adapter->nd_info->matches[i]); From 1b499cb72f26bbf44f2fa158c2d1487730aae96a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Sun, 24 Apr 2016 23:49:51 -0700 Subject: [PATCH 163/164] mwifiex: disable channel filtering feature in firmware As 2.4Ghz channels are overlapping, sometimes AP responds to probe request even if it's operating on neighbouring channel. Currently firmware drops those scan entries, as current channel doesn't match with APs channel. This patch enables MWIFIEX_DISABLE_CHAN_FILT flag in scan command to disable the feature so that better scan results will be received in 2.4Ghz band. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 36cc9cca95fc..bc5e52cebce1 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -498,11 +498,13 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, &= ~MWIFIEX_PASSIVE_SCAN; scan_chan_list[chan_idx].chan_number = (u32) ch->hw_value; + + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_DISABLE_CHAN_FILT; + if (filtered_scan) { scan_chan_list[chan_idx].max_scan_time = cpu_to_le16(adapter->specific_scan_time); - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; } chan_idx++; } @@ -1060,9 +1062,8 @@ mwifiex_config_scan(struct mwifiex_private *priv, scan_chan_list[chan_idx].chan_scan_mode_bitmap &= ~MWIFIEX_PASSIVE_SCAN; - if (*filtered_scan) - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_DISABLE_CHAN_FILT; if (user_scan_in->chan_list[chan_idx].scan_time) { scan_dur = (u16) user_scan_in-> From 9d3f65b0c2ddb926340af96eb89ad9be589865c0 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Sun, 24 Apr 2016 23:49:52 -0700 Subject: [PATCH 164/164] mwifiex: increase dwell time for active scan It's been observed that sometimes AP's probe response is received after scan duration gets completed for the channel. This happens especially when wildcard scan is performed along with specific SSID scan. We will increase the time from 30 msecs to 40 msecs. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 4c742a597cb0..0207af00be42 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -111,8 +111,8 @@ enum { #define SCAN_BEACON_ENTRY_PAD 6 #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110 -#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30 -#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30 +#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 40 +#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 40 #define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME 50 #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))