diff options
Diffstat (limited to 'drivers/net')
152 files changed, 2829 insertions, 2514 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 0b4d79659884..da466ab2d823 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -958,7 +958,7 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, * coherent DMA are unsupported */ dest_ring->base_addr_owner_space_unaligned = - dma_alloc_coherent(ar->dev, + dma_zalloc_coherent(ar->dev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), &base_addr, GFP_KERNEL); @@ -969,13 +969,6 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, dest_ring->base_addr_ce_space_unaligned = base_addr; - /* - * Correctly initialize memory to 0 to prevent garbage - * data crashing system when download firmware - */ - memset(dest_ring->base_addr_owner_space_unaligned, 0, - nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN); - dest_ring->base_addr_owner_space = PTR_ALIGN( dest_ring->base_addr_owner_space_unaligned, CE_DESC_RING_ALIGN); @@ -1130,3 +1123,42 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) ce_state->src_ring = NULL; ce_state->dest_ring = NULL; } + +void ath10k_ce_dump_registers(struct ath10k *ar, + struct ath10k_fw_crash_data *crash_data) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce_crash_data ce; + u32 addr, id; + + lockdep_assert_held(&ar->data_lock); + + ath10k_err(ar, "Copy Engine register dump:\n"); + + spin_lock_bh(&ar_pci->ce_lock); + for (id = 0; id < CE_COUNT; id++) { + addr = ath10k_ce_base_address(ar, id); + ce.base_addr = cpu_to_le32(addr); + + ce.src_wr_idx = + cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr)); + ce.src_r_idx = + cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr)); + ce.dst_wr_idx = + cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr)); + ce.dst_r_idx = + cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr)); + + if (crash_data) + crash_data->ce_crash_data[id] = ce; + + ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id, + le32_to_cpu(ce.base_addr), + le32_to_cpu(ce.src_wr_idx), + le32_to_cpu(ce.src_r_idx), + le32_to_cpu(ce.dst_wr_idx), + le32_to_cpu(ce.dst_r_idx)); + } + + spin_unlock_bh(&ar_pci->ce_lock); +} diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dfc098606bee..e76a98242b98 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -20,8 +20,6 @@ #include "hif.h" -/* Maximum number of Copy Engine's supported */ -#define CE_COUNT_MAX 12 #define CE_HTT_H2T_MSG_SRC_NENTRIES 8192 /* Descriptor rings must be aligned to this boundary */ @@ -228,6 +226,8 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_disable_interrupts(struct ath10k *ar); void ath10k_ce_enable_interrupts(struct ath10k *ar); +void ath10k_ce_dump_registers(struct ath10k *ar, + struct ath10k_fw_crash_data *crash_data); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 874c2a755c66..c2afcca6fd60 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -18,6 +18,8 @@ #include <linux/module.h> #include <linux/firmware.h> #include <linux/of.h> +#include <linux/dmi.h> +#include <linux/ctype.h> #include <asm/byteorder.h> #include "core.h" @@ -707,6 +709,72 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) return 0; } +static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data) +{ + struct ath10k *ar = data; + const char *bdf_ext; + const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC; + u8 bdf_enabled; + int i; + + if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE) + return; + + if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "wrong smbios bdf ext type length (%d).\n", + hdr->length); + return; + } + + bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET); + if (!bdf_enabled) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n"); + return; + } + + /* Only one string exists (per spec) */ + bdf_ext = (char *)hdr + hdr->length; + + if (memcmp(bdf_ext, magic, strlen(magic)) != 0) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "bdf variant magic does not match.\n"); + return; + } + + for (i = 0; i < strlen(bdf_ext); i++) { + if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "bdf variant name contains non ascii chars.\n"); + return; + } + } + + /* Copy extension name without magic suffix */ + if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic), + sizeof(ar->id.bdf_ext)) < 0) { + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", + bdf_ext); + return; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "found and validated bdf variant smbios_type 0x%x bdf %s\n", + ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext); +} + +static int ath10k_core_check_smbios(struct ath10k *ar) +{ + ar->id.bdf_ext[0] = '\0'; + dmi_walk(ath10k_core_check_bdfext, ar); + + if (ar->id.bdf_ext[0] == '\0') + return -ENODATA; + + return 0; +} + static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; @@ -1053,6 +1121,9 @@ err: static int ath10k_core_create_board_name(struct ath10k *ar, char *name, size_t name_len) { + /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ + char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH]; + if (ar->id.bmi_ids_valid) { scnprintf(name, name_len, "bus=%s,bmi-chip-id=%d,bmi-board-id=%d", @@ -1062,12 +1133,15 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name, goto out; } + if (ar->id.bdf_ext[0] != '\0') + scnprintf(variant, sizeof(variant), ",variant=%s", + ar->id.bdf_ext); + scnprintf(name, name_len, - "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x", + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s", ath10k_bus_str(ar->hif.bus), ar->id.vendor, ar->id.device, - ar->id.subsystem_vendor, ar->id.subsystem_device); - + ar->id.subsystem_vendor, ar->id.subsystem_device, variant); out: ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); @@ -2128,6 +2202,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_free_firmware_files; } + ret = ath10k_core_check_smbios(ar); + if (ret) + ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n"); + ret = ath10k_core_fetch_board_file(ar); if (ret) { ath10k_err(ar, "failed to fetch board file: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c7664d6569fa..88d14be7fcce 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -69,6 +69,23 @@ #define ATH10K_NAPI_BUDGET 64 #define ATH10K_NAPI_QUOTA_LIMIT 60 +/* SMBIOS type containing Board Data File Name Extension */ +#define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8 + +/* SMBIOS type structure length (excluding strings-set) */ +#define ATH10K_SMBIOS_BDF_EXT_LENGTH 0x9 + +/* Offset pointing to Board Data File Name Extension */ +#define ATH10K_SMBIOS_BDF_EXT_OFFSET 0x8 + +/* Board Data File Name Extension string length. + * String format: BDF_<Customer ID>_<Extension>\0 + */ +#define ATH10K_SMBIOS_BDF_EXT_STR_LENGTH 0x20 + +/* The magic used by QCA spec */ +#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_" + struct ath10k; enum ath10k_bus { @@ -314,6 +331,7 @@ struct ath10k_peer { struct ieee80211_vif *vif; struct ieee80211_sta *sta; + bool removed; int vdev_id; u8 addr[ETH_ALEN]; DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); @@ -419,6 +437,21 @@ struct ath10k_vif_iter { struct ath10k_vif *arvif; }; +/* Copy Engine register dump, protected by ce-lock */ +struct ath10k_ce_crash_data { + __le32 base_addr; + __le32 src_wr_idx; + __le32 src_r_idx; + __le32 dst_wr_idx; + __le32 dst_r_idx; +}; + +struct ath10k_ce_crash_hdr { + __le32 ce_count; + __le32 reserved[3]; /* for future use */ + struct ath10k_ce_crash_data entries[]; +}; + /* used for crash-dump storage, protected by data-lock */ struct ath10k_fw_crash_data { bool crashed_since_read; @@ -426,6 +459,7 @@ struct ath10k_fw_crash_data { uuid_le uuid; struct timespec timestamp; __le32 registers[REG_DUMP_COUNT_QCA988X]; + struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX]; }; struct ath10k_debug { @@ -781,6 +815,8 @@ struct ath10k { bool bmi_ids_valid; u8 bmi_board_id; u8 bmi_chip_id; + + char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH]; } id; int fw_api; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index e1a70dffc52a..d5ff0f4ef5ce 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -41,6 +41,7 @@ */ enum ath10k_fw_crash_dump_type { ATH10K_FW_CRASH_DUMP_REGISTERS = 0, + ATH10K_FW_CRASH_DUMP_CE_DATA = 1, ATH10K_FW_CRASH_DUMP_MAX, }; @@ -400,6 +401,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * prevent firmware from DoS-ing the host. */ ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); + ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd); ath10k_warn(ar, "dropping fw peer stats\n"); goto free; } @@ -410,10 +412,12 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } + if (!list_empty(&stats.peers)) + list_splice_tail_init(&stats.peers_extd, + &ar->debug.fw_stats.peers_extd); + list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs); - list_splice_tail_init(&stats.peers_extd, - &ar->debug.fw_stats.peers_extd); } complete(&ar->debug.fw_stats_complete); @@ -726,6 +730,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, bool mark_read) { struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data; + struct ath10k_ce_crash_hdr *ce_hdr; struct ath10k_dump_file_data *dump_data; struct ath10k_tlv_dump_data *dump_tlv; int hdr_len = sizeof(*dump_data); @@ -734,6 +739,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, len = hdr_len; len += sizeof(*dump_tlv) + sizeof(crash_data->registers); + len += sizeof(*dump_tlv) + sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0]); sofar += hdr_len; @@ -792,6 +799,18 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, sizeof(crash_data->registers)); sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers); + dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar); + dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_CE_DATA); + dump_tlv->tlv_len = cpu_to_le32(sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0])); + ce_hdr = (struct ath10k_ce_crash_hdr *)(dump_tlv->tlv_data); + ce_hdr->ce_count = cpu_to_le32(CE_COUNT); + memset(ce_hdr->reserved, 0, sizeof(ce_hdr->reserved)); + memcpy(ce_hdr->entries, crash_data->ce_crash_data, + CE_COUNT * sizeof(ce_hdr->entries[0])); + sofar += sizeof(*dump_tlv) + sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0]); + ar->debug.fw_crash_data->crashed_since_read = !mark_read; spin_unlock_bh(&ar->data_lock); diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 175aae38c375..9f6a915f91bf 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -474,33 +474,16 @@ static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc) } } -static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc) -{ - struct ath10k_htc_svc_tx_credits *entry; - - entry = &htc->service_tx_alloc[0]; - - /* - * for PCIE allocate all credists/HTC buffers to WMI. - * no buffers are used/required for data. data always - * remains on host. - */ - entry++; - entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; - entry->credit_allocation = htc->total_transmit_credits; -} - static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc, u16 service_id) { u8 allocation = 0; - int i; - for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) { - if (htc->service_tx_alloc[i].service_id == service_id) - allocation = - htc->service_tx_alloc[i].credit_allocation; - } + /* The WMI control service is the only service with flow control. + * Let it have all transmit credits. + */ + if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL) + allocation = htc->total_transmit_credits; return allocation; } @@ -574,8 +557,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) return -ECOMM; } - ath10k_htc_setup_target_buffer_assignments(htc); - /* setup our pseudo HTC control endpoint connection */ memset(&conn_req, 0, sizeof(conn_req)); memset(&conn_resp, 0, sizeof(conn_resp)); @@ -726,12 +707,6 @@ setup: ep->max_tx_queue_depth = conn_req->max_send_queue_depth; ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size); ep->tx_credits = tx_alloc; - ep->tx_credit_size = htc->target_credit_size; - ep->tx_credits_per_max_message = ep->max_ep_message_len / - htc->target_credit_size; - - if (ep->max_ep_message_len % htc->target_credit_size) - ep->tx_credits_per_max_message++; /* copy all the callbacks */ ep->ep_ops = conn_req->ep_ops; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 0c55cd92a951..6ababa345e2b 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -314,8 +314,6 @@ struct ath10k_htc_ep { u8 seq_no; /* for debugging */ int tx_credits; - int tx_credit_size; - int tx_credits_per_max_message; bool tx_credit_flow_enabled; }; @@ -339,7 +337,6 @@ struct ath10k_htc { struct completion ctl_resp; int total_transmit_credits; - struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; int target_credit_size; }; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 0bc7fe8c4b52..2743a9bcd556 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -702,6 +702,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, /* 80MHZ */ case 2: status->vht_flag |= RX_VHT_FLAG_80MHZ; + break; + case 3: + status->vht_flag |= RX_VHT_FLAG_160MHZ; + break; } status->flag |= RX_FLAG_VHT; @@ -926,7 +930,7 @@ static void ath10k_process_rx(struct ath10k *ar, *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, - "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", + "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", skb, skb->len, ieee80211_get_SA(hdr), @@ -940,6 +944,7 @@ static void ath10k_process_rx(struct ath10k *ar, status->flag & RX_FLAG_VHT ? "vht" : "", status->flag & RX_FLAG_40MHZ ? "40" : "", status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "", + status->vht_flag & RX_VHT_FLAG_160MHZ ? "160" : "", status->flag & RX_FLAG_SHORT_GI ? "sgi " : "", status->rate_idx, status->vht_nss, @@ -2231,6 +2236,8 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, return; } + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + if (txrate.flags == WMI_RATE_PREAMBLE_CCK || txrate.flags == WMI_RATE_PREAMBLE_OFDM) { rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode); @@ -2245,7 +2252,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, rate *= 10; if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK) rate = rate - 5; - arsta->txrate.legacy = rate * 10; + arsta->txrate.legacy = rate; } else if (txrate.flags == WMI_RATE_PREAMBLE_HT) { arsta->txrate.flags = RATE_INFO_FLAGS_MCS; arsta->txrate.mcs = txrate.mcs; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 7feffec531cc..38aa7c95732e 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -578,6 +578,9 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define TARGET_10_4_IPHDR_PAD_CONFIG 1 #define TARGET_10_4_QWRAP_CONFIG 0 +/* Maximum number of Copy Engine's supported */ +#define CE_COUNT_MAX 12 + /* Number of Copy Engines supported */ #define CE_COUNT ar->hw_values->ce_count diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d1b7edba5e49..9977829a6ec4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -569,10 +569,14 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) case NL80211_CHAN_WIDTH_80: phymode = MODE_11AC_VHT80; break; + case NL80211_CHAN_WIDTH_160: + phymode = MODE_11AC_VHT160; + break; + case NL80211_CHAN_WIDTH_80P80: + phymode = MODE_11AC_VHT80_80; + break; case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: - case NL80211_CHAN_WIDTH_80P80: - case NL80211_CHAN_WIDTH_160: phymode = MODE_UNKNOWN; break; } @@ -971,6 +975,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) arg.vdev_id = vdev_id; arg.channel.freq = channel->center_freq; arg.channel.band_center_freq1 = chandef->center_freq1; + arg.channel.band_center_freq2 = chandef->center_freq2; /* TODO setup this dynamically, what in case we don't have any vifs? */ @@ -1417,6 +1422,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, arg.channel.freq = chandef->chan->center_freq; arg.channel.band_center_freq1 = chandef->center_freq1; + arg.channel.band_center_freq2 = chandef->center_freq2; arg.channel.mode = chan_to_phymode(chandef); arg.channel.min_power = 0; @@ -2480,6 +2486,9 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, if (sta->bandwidth == IEEE80211_STA_RX_BW_80) arg->peer_flags |= ar->wmi.peer_flags->bw80; + if (sta->bandwidth == IEEE80211_STA_RX_BW_160) + arg->peer_flags |= ar->wmi.peer_flags->bw160; + arg->peer_vht_rates.rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest); arg->peer_vht_rates.rx_mcs_set = @@ -2533,6 +2542,33 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) ATH10K_MAC_FIRST_OFDM_RATE_IDX; } +static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar, + struct ieee80211_sta *sta) +{ + if (sta->bandwidth == IEEE80211_STA_RX_BW_160) { + switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: + return MODE_11AC_VHT160; + case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: + return MODE_11AC_VHT80_80; + default: + /* not sure if this is a valid case? */ + return MODE_11AC_VHT160; + } + } + + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AC_VHT80; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AC_VHT40; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AC_VHT20; + + return MODE_UNKNOWN; +} + static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2579,12 +2615,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, */ if (sta->vht_cap.vht_supported && !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) - phymode = MODE_11AC_VHT80; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) - phymode = MODE_11AC_VHT40; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_20) - phymode = MODE_11AC_VHT20; + phymode = ath10k_mac_get_phymode_vht(ar, sta); } else if (sta->ht_cap.ht_supported && !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) { if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) @@ -3774,6 +3805,9 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, if (!peer) return NULL; + if (peer->removed) + return NULL; + if (peer->sta) return peer->sta->txq[tid]; else if (peer->vif) @@ -4311,6 +4345,13 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) vht_cap.cap |= val; } + /* Currently the firmware seems to be buggy, don't enable 80+80 + * mode until that's resolved. + */ + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && + !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) + vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + mcs_map = 0; for (i = 0; i < 8; i++) { if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) @@ -6969,6 +7010,9 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, bw = WMI_PEER_CHWIDTH_80MHZ; break; case IEEE80211_STA_RX_BW_160: + bw = WMI_PEER_CHWIDTH_160MHZ; + break; + default: ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n", sta->bandwidth, sta->addr); bw = WMI_PEER_CHWIDTH_20MHZ; @@ -7476,6 +7520,20 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, return 0; } +static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath10k *ar; + struct ath10k_peer *peer; + + ar = hw->priv; + + list_for_each_entry(peer, &ar->peers, list) + if (peer->sta == sta) + peer->removed = true; +} + static const struct ieee80211_ops ath10k_ops = { .tx = ath10k_mac_op_tx, .wake_tx_queue = ath10k_mac_op_wake_tx_queue, @@ -7516,6 +7574,7 @@ static const struct ieee80211_ops ath10k_ops = { .assign_vif_chanctx = ath10k_mac_op_assign_vif_chanctx, .unassign_vif_chanctx = ath10k_mac_op_unassign_vif_chanctx, .switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx, + .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove, CFG80211_TESTMODE_CMD(ath10k_tm_cmd) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index e757c514e2b7..79e61459bc6c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -896,7 +896,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, */ alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT); - data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, + data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev, alloc_nbytes, &ce_data_base, GFP_ATOMIC); @@ -905,7 +905,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ret = -ENOMEM; goto done; } - memset(data_buf, 0, alloc_nbytes); remaining_bytes = nbytes; ce_data = ce_data_base; @@ -1474,6 +1473,7 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) ath10k_err(ar, "firmware crashed! (uuid %s)\n", uuid); ath10k_print_driver_info(ar); ath10k_pci_dump_registers(ar, crash_data); + ath10k_ce_dump_registers(ar, crash_data); spin_unlock_bh(&ar->data_lock); @@ -1937,7 +1937,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar) { u32 addr, val; - addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; + addr = SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS; val = ath10k_pci_read32(ar, addr); val |= CORE_CTRL_CPU_INTR_MASK; ath10k_pci_write32(ar, addr, val); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 9854ad56b2de..c76789d5de99 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -25,11 +25,6 @@ #include "ahb.h" /* - * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite - */ -#define DIAG_TRANSFER_LIMIT 2048 - -/* * maximum number of bytes that can be * handled atomically by DiagRead/DiagWrite */ diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 1f6bb9e8bb01..f9188027a6f6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3637,6 +3637,7 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { .vht = WMI_TLV_PEER_VHT, .bw80 = WMI_TLV_PEER_80MHZ, .pmf = WMI_TLV_PEER_PMF, + .bw160 = WMI_TLV_PEER_160MHZ, }; /************/ diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index b8aa6000573c..22cf011e839a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -543,6 +543,7 @@ enum wmi_tlv_peer_flags { WMI_TLV_PEER_VHT = 0x02000000, WMI_TLV_PEER_80MHZ = 0x04000000, WMI_TLV_PEER_PMF = 0x08000000, + WMI_TLV_PEER_160MHZ = 0x20000000, }; enum wmi_tlv_tag { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 50d6ee6afe26..414ad3e1eed4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -28,6 +28,7 @@ #include "wmi-ops.h" #include "p2p.h" #include "hw.h" +#include "hif.h" #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9 #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ) @@ -1574,6 +1575,7 @@ static const struct wmi_peer_flags_map wmi_peer_flags_map = { .bw80 = WMI_PEER_80MHZ, .vht_2g = WMI_PEER_VHT_2G, .pmf = WMI_PEER_PMF, + .bw160 = WMI_PEER_160MHZ, }; static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = { @@ -1591,6 +1593,7 @@ static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = { .spatial_mux = WMI_10X_PEER_SPATIAL_MUX, .vht = WMI_10X_PEER_VHT, .bw80 = WMI_10X_PEER_80MHZ, + .bw160 = WMI_10X_PEER_160MHZ, }; static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = { @@ -1610,6 +1613,7 @@ static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = { .bw80 = WMI_10_2_PEER_80MHZ, .vht_2g = WMI_10_2_PEER_VHT_2G, .pmf = WMI_10_2_PEER_PMF, + .bw160 = WMI_10_2_PEER_160MHZ, }; void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, @@ -1634,7 +1638,10 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, ch->mhz = __cpu_to_le32(arg->freq); ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1); - ch->band_center_freq2 = 0; + if (arg->mode == MODE_11AC_VHT80_80) + ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2); + else + ch->band_center_freq2 = 0; ch->min_power = arg->min_power; ch->max_power = arg->max_power; ch->reg_power = arg->max_reg_power; @@ -2319,7 +2326,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) */ if (channel >= 1 && channel <= 14) { status->band = NL80211_BAND_2GHZ; - } else if (channel >= 36 && channel <= 165) { + } else if (channel >= 36 && channel <= 169) { status->band = NL80211_BAND_5GHZ; } else { /* Shouldn't happen unless list of advertised channels to diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 5d3dff95b2e5..861c2d8c6e8c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1728,8 +1728,10 @@ enum wmi_phy_mode { MODE_11AC_VHT20_2G = 11, MODE_11AC_VHT40_2G = 12, MODE_11AC_VHT80_2G = 13, - MODE_UNKNOWN = 14, - MODE_MAX = 14 + MODE_11AC_VHT80_80 = 14, + MODE_11AC_VHT160 = 15, + MODE_UNKNOWN = 16, + MODE_MAX = 16 }; static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) @@ -1757,6 +1759,10 @@ static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) return "11ac-vht40"; case MODE_11AC_VHT80: return "11ac-vht80"; + case MODE_11AC_VHT160: + return "11ac-vht160"; + case MODE_11AC_VHT80_80: + return "11ac-vht80+80"; case MODE_11AC_VHT20_2G: return "11ac-vht20-2g"; case MODE_11AC_VHT40_2G: @@ -1811,6 +1817,7 @@ struct wmi_channel { struct wmi_channel_arg { u32 freq; u32 band_center_freq1; + u32 band_center_freq2; bool passive; bool allow_ibss; bool allow_ht; @@ -1875,9 +1882,18 @@ enum wmi_channel_change_cause { #define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003 #define WMI_VHT_CAP_RX_LDPC 0x00000010 #define WMI_VHT_CAP_SGI_80MHZ 0x00000020 +#define WMI_VHT_CAP_SGI_160MHZ 0x00000040 #define WMI_VHT_CAP_TX_STBC 0x00000080 #define WMI_VHT_CAP_RX_STBC_MASK 0x00000300 #define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8 +#define WMI_VHT_CAP_SU_BFER 0x00000800 +#define WMI_VHT_CAP_SU_BFEE 0x00001000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK 0x0000E000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK_SHIFT 13 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK 0x00070000 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK_SHIFT 16 +#define WMI_VHT_CAP_MU_BFER 0x00080000 +#define WMI_VHT_CAP_MU_BFEE 0x00100000 #define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000 #define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23 #define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000 @@ -1926,6 +1942,8 @@ enum { REGDMN_MODE_11AC_VHT40PLUS = 0x40000, /* 5Ghz, VHT40 + channels */ REGDMN_MODE_11AC_VHT40MINUS = 0x80000, /* 5Ghz VHT40 - channels */ REGDMN_MODE_11AC_VHT80 = 0x100000, /* 5Ghz, VHT80 channels */ + REGDMN_MODE_11AC_VHT160 = 0x200000, /* 5Ghz, VHT160 channels */ + REGDMN_MODE_11AC_VHT80_80 = 0x400000, /* 5Ghz, VHT80+80 channels */ REGDMN_MODE_ALL = 0xffffffff }; @@ -5783,6 +5801,7 @@ enum wmi_peer_chwidth { WMI_PEER_CHWIDTH_20MHZ = 0, WMI_PEER_CHWIDTH_40MHZ = 1, WMI_PEER_CHWIDTH_80MHZ = 2, + WMI_PEER_CHWIDTH_160MHZ = 3, }; enum wmi_peer_param { @@ -5873,6 +5892,7 @@ struct wmi_peer_flags_map { u32 bw80; u32 vht_2g; u32 pmf; + u32 bw160; }; enum wmi_peer_flags { @@ -5892,6 +5912,7 @@ enum wmi_peer_flags { WMI_PEER_80MHZ = 0x04000000, WMI_PEER_VHT_2G = 0x08000000, WMI_PEER_PMF = 0x10000000, + WMI_PEER_160MHZ = 0x20000000 }; enum wmi_10x_peer_flags { @@ -5909,6 +5930,7 @@ enum wmi_10x_peer_flags { WMI_10X_PEER_SPATIAL_MUX = 0x00200000, WMI_10X_PEER_VHT = 0x02000000, WMI_10X_PEER_80MHZ = 0x04000000, + WMI_10X_PEER_160MHZ = 0x20000000 }; enum wmi_10_2_peer_flags { @@ -5928,6 +5950,7 @@ enum wmi_10_2_peer_flags { WMI_10_2_PEER_80MHZ = 0x04000000, WMI_10_2_PEER_VHT_2G = 0x08000000, WMI_10_2_PEER_PMF = 0x10000000, + WMI_10_2_PEER_160MHZ = 0x20000000 }; /* diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index dc44cfef7517..16e052d02c94 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -502,8 +502,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; return -EOPNOTSUPP; default: - WARN_ON(1); - return -EINVAL; + return -EOPNOTSUPP; } mutex_lock(&ah->lock); diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 8ec66e74d06d..2195b1b7a8a6 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -713,7 +713,7 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) * that the packet is properly freed? */ if (s_req->busrequest) { - s_req->busrequest->scat_req = 0; + s_req->busrequest->scat_req = NULL; ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest); } kfree(s_req->virt_dma_buf); diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 8f231c67dd51..783a38f1a626 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -3,8 +3,8 @@ config ATH9K_HW config ATH9K_COMMON tristate select ATH_COMMON - select DEBUG_FS - select RELAY +config ATH9K_COMMON_DEBUG + bool config ATH9K_DFS_DEBUGFS def_bool y depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED @@ -60,12 +60,14 @@ config ATH9K_DEBUGFS bool "Atheros ath9k debugging" depends on ATH9K && DEBUG_FS select MAC80211_DEBUGFS + select ATH9K_COMMON_DEBUG select RELAY ---help--- Say Y, if you need access to ath9k's statistics for interrupts, rate control, etc. Also required for changing debug message flags at run time. + As well as access to the FFT/spectral data and TX99. config ATH9K_STATION_STATISTICS bool "Detailed station statistics" @@ -174,8 +176,11 @@ config ATH9K_HTC config ATH9K_HTC_DEBUGFS bool "Atheros ath9k_htc debugging" depends on ATH9K_HTC && DEBUG_FS + select ATH9K_COMMON_DEBUG + select RELAY ---help--- Say Y, if you need access to ath9k_htc's statistics. + As well as access to the FFT/spectral data. config ATH9K_HWRNG bool "Random number generator support" diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 76f9dc37500b..36a40ffdce15 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -60,8 +60,9 @@ obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o \ common-init.o \ common-beacon.o \ - common-debug.o \ - common-spectral.o + +ath9k_common-$(CONFIG_ATH9K_COMMON_DEBUG) += common-debug.o \ + common-spectral.o ath9k_htc-y += htc_hst.o \ hif_usb.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index f816909d9474..4b3c9b108197 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -220,8 +220,8 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ads->ds_txstatus6 = ads->ds_txstatus7 = 0; ads->ds_txstatus8 = ads->ds_txstatus9 = 0; - ACCESS_ONCE(ads->ds_link) = i->link; - ACCESS_ONCE(ads->ds_data) = i->buf_addr[0]; + WRITE_ONCE(ads->ds_link, i->link); + WRITE_ONCE(ads->ds_data, i->buf_addr[0]); ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore); ctl6 = SM(i->keytype, AR_EncrType); @@ -235,26 +235,26 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) if ((i->is_first || i->is_last) && i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) { - ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0) + WRITE_ONCE(ads->ds_ctl2, set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); + | SM(0, AR_BurstDur)); - ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0) + WRITE_ONCE(ads->ds_ctl3, set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) - | set11nRate(i->rates, 3); + | set11nRate(i->rates, 3)); } else { - ACCESS_ONCE(ads->ds_ctl2) = 0; - ACCESS_ONCE(ads->ds_ctl3) = 0; + WRITE_ONCE(ads->ds_ctl2, 0); + WRITE_ONCE(ads->ds_ctl3, 0); } if (!i->is_first) { - ACCESS_ONCE(ads->ds_ctl0) = 0; - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + WRITE_ONCE(ads->ds_ctl0, 0); + WRITE_ONCE(ads->ds_ctl1, ctl1); + WRITE_ONCE(ads->ds_ctl6, ctl6); return; } @@ -279,7 +279,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) break; } - ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) + WRITE_ONCE(ads->ds_ctl0, (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower[0], AR_XmitPower0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -287,29 +287,29 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : - (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); + (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + WRITE_ONCE(ads->ds_ctl1, ctl1); + WRITE_ONCE(ads->ds_ctl6, ctl6); if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST) return; - ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0) - | set11nPktDurRTSCTS(i->rates, 1); + WRITE_ONCE(ads->ds_ctl4, set11nPktDurRTSCTS(i->rates, 0) + | set11nPktDurRTSCTS(i->rates, 1)); - ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2) - | set11nPktDurRTSCTS(i->rates, 3); + WRITE_ONCE(ads->ds_ctl5, set11nPktDurRTSCTS(i->rates, 2) + | set11nPktDurRTSCTS(i->rates, 3)); - ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0) + WRITE_ONCE(ads->ds_ctl7, set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) - | SM(i->rtscts_rate, AR_RTSCTSRate); + | SM(i->rtscts_rate, AR_RTSCTSRate)); - ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1); - ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2); - ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3); + WRITE_ONCE(ads->ds_ctl9, SM(i->txpower[1], AR_XmitPower1)); + WRITE_ONCE(ads->ds_ctl10, SM(i->txpower[2], AR_XmitPower2)); + WRITE_ONCE(ads->ds_ctl11, SM(i->txpower[3], AR_XmitPower3)); } static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, @@ -318,7 +318,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ar5416_desc *ads = AR5416DESC(ds); u32 status; - status = ACCESS_ONCE(ads->ds_txstatus9); + status = READ_ONCE(ads->ds_txstatus9); if ((status & AR_TxDone) == 0) return -EINPROGRESS; @@ -332,7 +332,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_rateindex = MS(status, AR_FinalTxIdx); ts->ts_seqnum = MS(status, AR_SeqNum); - status = ACCESS_ONCE(ads->ds_txstatus0); + status = READ_ONCE(ads->ds_txstatus0); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); @@ -342,7 +342,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ba_high = ads->AR_BaBitmapHigh; } - status = ACCESS_ONCE(ads->ds_txstatus1); + status = READ_ONCE(ads->ds_txstatus1); if (status & AR_FrmXmitOK) ts->ts_status |= ATH9K_TX_ACKED; else { @@ -371,7 +371,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_longretry = MS(status, AR_DataFailCnt); ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - status = ACCESS_ONCE(ads->ds_txstatus5); + status = READ_ONCE(ads->ds_txstatus5); ts->ts_rssi = MS(status, AR_TxRSSICombined); ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); @@ -390,13 +390,13 @@ static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index) switch (index) { case 0: - return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0); + return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur0); case 1: - return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1); + return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur1); case 2: - return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2); + return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur2); case 3: - return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3); + return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur3); default: return -1; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index da84b705cbcd..cc5bb0a76baf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -39,47 +39,47 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) (i->qcu << AR_TxQcuNum_S) | desc_len; checksum += val; - ACCESS_ONCE(ads->info) = val; + WRITE_ONCE(ads->info, val); checksum += i->link; - ACCESS_ONCE(ads->link) = i->link; + WRITE_ONCE(ads->link, i->link); checksum += i->buf_addr[0]; - ACCESS_ONCE(ads->data0) = i->buf_addr[0]; + WRITE_ONCE(ads->data0, i->buf_addr[0]); checksum += i->buf_addr[1]; - ACCESS_ONCE(ads->data1) = i->buf_addr[1]; + WRITE_ONCE(ads->data1, i->buf_addr[1]); checksum += i->buf_addr[2]; - ACCESS_ONCE(ads->data2) = i->buf_addr[2]; + WRITE_ONCE(ads->data2, i->buf_addr[2]); checksum += i->buf_addr[3]; - ACCESS_ONCE(ads->data3) = i->buf_addr[3]; + WRITE_ONCE(ads->data3, i->buf_addr[3]); checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl3) = val; + WRITE_ONCE(ads->ctl3, val); checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl5) = val; + WRITE_ONCE(ads->ctl5, val); checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl7) = val; + WRITE_ONCE(ads->ctl7, val); checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl9) = val; + WRITE_ONCE(ads->ctl9, val); checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); - ACCESS_ONCE(ads->ctl10) = checksum; + WRITE_ONCE(ads->ctl10, checksum); if (i->is_first || i->is_last) { - ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0) + WRITE_ONCE(ads->ctl13, set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); + | SM(0, AR_BurstDur)); - ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0) + WRITE_ONCE(ads->ctl14, set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) - | set11nRate(i->rates, 3); + | set11nRate(i->rates, 3)); } else { - ACCESS_ONCE(ads->ctl13) = 0; - ACCESS_ONCE(ads->ctl14) = 0; + WRITE_ONCE(ads->ctl13, 0); + WRITE_ONCE(ads->ctl14, 0); } ads->ctl20 = 0; @@ -89,17 +89,17 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ctl17 = SM(i->keytype, AR_EncrType); if (!i->is_first) { - ACCESS_ONCE(ads->ctl11) = 0; - ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore; - ACCESS_ONCE(ads->ctl15) = 0; - ACCESS_ONCE(ads->ctl16) = 0; - ACCESS_ONCE(ads->ctl17) = ctl17; - ACCESS_ONCE(ads->ctl18) = 0; - ACCESS_ONCE(ads->ctl19) = 0; + WRITE_ONCE(ads->ctl11, 0); + WRITE_ONCE(ads->ctl12, i->is_last ? 0 : AR_TxMore); + WRITE_ONCE(ads->ctl15, 0); + WRITE_ONCE(ads->ctl16, 0); + WRITE_ONCE(ads->ctl17, ctl17); + WRITE_ONCE(ads->ctl18, 0); + WRITE_ONCE(ads->ctl19, 0); return; } - ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) + WRITE_ONCE(ads->ctl11, (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower[0], AR_XmitPower0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -107,7 +107,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : - (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); + (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0) @@ -135,26 +135,26 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; ctl12 |= SM(val, AR_PAPRDChainMask); - ACCESS_ONCE(ads->ctl12) = ctl12; - ACCESS_ONCE(ads->ctl17) = ctl17; + WRITE_ONCE(ads->ctl12, ctl12); + WRITE_ONCE(ads->ctl17, ctl17); - ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) - | set11nPktDurRTSCTS(i->rates, 1); + WRITE_ONCE(ads->ctl15, set11nPktDurRTSCTS(i->rates, 0) + | set11nPktDurRTSCTS(i->rates, 1)); - ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) - | set11nPktDurRTSCTS(i->rates, 3); + WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2) + | set11nPktDurRTSCTS(i->rates, 3)); - ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0) + WRITE_ONCE(ads->ctl18, set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) - | SM(i->rtscts_rate, AR_RTSCTSRate); + | SM(i->rtscts_rate, AR_RTSCTSRate)); - ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; + WRITE_ONCE(ads->ctl19, AR_Not_Sounding); - ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1); - ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2); - ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3); + WRITE_ONCE(ads->ctl20, SM(i->txpower[1], AR_XmitPower1)); + WRITE_ONCE(ads->ctl21, SM(i->txpower[2], AR_XmitPower2)); + WRITE_ONCE(ads->ctl22, SM(i->txpower[3], AR_XmitPower3)); } static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) @@ -359,7 +359,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ads = &ah->ts_ring[ah->ts_tail]; - status = ACCESS_ONCE(ads->status8); + status = READ_ONCE(ads->status8); if ((status & AR_TxDone) == 0) return -EINPROGRESS; @@ -385,7 +385,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, if (status & AR_TxOpExceeded) ts->ts_status |= ATH9K_TXERR_XTXOP; - status = ACCESS_ONCE(ads->status2); + status = READ_ONCE(ads->status2); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); @@ -395,7 +395,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ba_high = ads->status6; } - status = ACCESS_ONCE(ads->status3); + status = READ_ONCE(ads->status3); if (status & AR_ExcessiveRetries) ts->ts_status |= ATH9K_TXERR_XRETRY; if (status & AR_Filtered) @@ -420,7 +420,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_longretry = MS(status, AR_DataFailCnt); ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - status = ACCESS_ONCE(ads->status7); + status = READ_ONCE(ads->status7); ts->ts_rssi = MS(status, AR_TxRSSICombined); ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); @@ -437,13 +437,13 @@ static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index) switch (index) { case 0: - return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0); + return MS(READ_ONCE(adc->ctl15), AR_PacketDur0); case 1: - return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1); + return MS(READ_ONCE(adc->ctl15), AR_PacketDur1); case 2: - return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2); + return MS(READ_ONCE(adc->ctl16), AR_PacketDur2); case 3: - return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3); + return MS(READ_ONCE(adc->ctl16), AR_PacketDur3); default: return 0; } diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h index 7c9788490f7f..3376990d3a24 100644 --- a/drivers/net/wireless/ath/ath9k/common-debug.h +++ b/drivers/net/wireless/ath/ath9k/common-debug.h @@ -60,6 +60,7 @@ struct ath_rx_stats { u32 rx_spectral; }; +#ifdef CONFIG_ATH9K_COMMON_DEBUG void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, struct ath_hw *ah); void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, @@ -70,3 +71,29 @@ void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, struct ath_rx_stats *rxstats); void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, struct ath_rx_stats *rxstats); +#else +static inline void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah) +{ +} + +static inline void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah) +{ +} + +static inline void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, + struct ath_rx_status *rs) +{ +} + +static inline void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, + struct ath_rx_stats *rxstats) +{ +} + +static inline void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, + struct ath_rx_stats *rxstats) +{ +} +#endif /* CONFIG_ATH9K_COMMON_DEBUG */ diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index eedf86b67cf5..789a3dbe8341 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -1075,7 +1075,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) { - if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + if (spec_priv->rfs_chan_spec_scan) { relay_close(spec_priv->rfs_chan_spec_scan); spec_priv->rfs_chan_spec_scan = NULL; } diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h index 998743be9c67..5d1a51d83aa6 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.h +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h @@ -151,6 +151,7 @@ static inline u8 spectral_bitmap_weight(u8 *bins) return bins[0] & 0x3f; } +#ifdef CONFIG_ATH9K_COMMON_DEBUG void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); @@ -161,5 +162,27 @@ int ath9k_cmn_spectral_scan_config(struct ath_common *common, enum spectral_mode spectral_mode); int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf); +#else +static inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, + struct dentry *debugfs_phy) +{ +} + +static inline void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) +{ +} + +static inline void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) +{ +} + +static inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, + struct ieee80211_hdr *hdr, + struct ath_rx_status *rs, u64 tsf) +{ + return 0; +} +#endif /* CONFIG_ATH9K_COMMON_DEBUG */ #endif /* SPECTRAL_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 4a01ebe53053..b8c0a08066a0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -72,7 +72,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_4k_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_4k_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 9611f020f7c0..3caa149b1013 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -75,7 +75,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_ar9287_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_ar9287_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 7d5223451ce9..56b44fc7a8e6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -131,7 +131,7 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_def_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a35f78be8dec..ac36873d6da4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -731,7 +731,7 @@ u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) udelay(100); if (WARN_ON_ONCE(i >= 100)) { - ath_err(common, "PLL4 meaurement not done\n"); + ath_err(common, "PLL4 measurement not done\n"); break; } diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig index 591ebaea8265..4b83e87f0b94 100644 --- a/drivers/net/wireless/ath/wcn36xx/Kconfig +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig @@ -1,6 +1,8 @@ config WCN36XX tristate "Qualcomm Atheros WCN3660/3680 support" depends on MAC80211 && HAS_DMA + depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n + depends on QCOM_SMD || QCOM_SMD=n ---help--- This module adds support for wireless adapters based on Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 231fd022f0f5..87dfdaf9044c 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -23,6 +23,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/interrupt.h> +#include <linux/soc/qcom/smem_state.h> #include "wcn36xx.h" #include "txrx.h" @@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) goto out_err; /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ - ret = wcn->ctrl_ops->smsm_change_state( - WCN36XX_SMSM_WLAN_TX_ENABLE, - WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); + ret = qcom_smem_state_update_bits(wcn->tx_enable_state, + WCN36XX_SMSM_WLAN_TX_ENABLE | + WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY, + WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); + if (ret) + goto out_err; return 0; @@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, * notify chip about new frame through SMSM bus. */ if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { - wcn->ctrl_ops->smsm_change_state( - 0, - WCN36XX_SMSM_WLAN_TX_ENABLE); + qcom_smem_state_update_bits(wcn->tx_rings_empty_state, + WCN36XX_SMSM_WLAN_TX_ENABLE, + WCN36XX_SMSM_WLAN_TX_ENABLE); } else { /* indicate End Of Packet and generate interrupt on descriptor * done. diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 4f87ef1e1eb8..b765c647319d 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -350,6 +350,8 @@ enum wcn36xx_hal_host_msg_type { WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233, + WCN36XX_HAL_PRINT_REG_INFO_IND = 259, + WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE }; @@ -4703,4 +4705,18 @@ struct stats_class_b_ind { u32 rx_time_total; }; +/* WCN36XX_HAL_PRINT_REG_INFO_IND */ +struct wcn36xx_hal_print_reg_info_ind { + struct wcn36xx_hal_msg_header header; + + u32 count; + u32 scenario; + u32 reason; + + struct { + u32 addr; + u32 value; + } regs[]; +} __packed; + #endif /* _HAL_H_ */ diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index e1d59da2ad20..0002190c9041 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -21,6 +21,10 @@ #include <linux/platform_device.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/soc/qcom/smd.h> +#include <linux/soc/qcom/smem_state.h> +#include <linux/soc/qcom/wcnss_ctrl.h> #include "wcn36xx.h" unsigned int wcn36xx_dbg_mask; @@ -564,23 +568,59 @@ out: return ret; } -static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *mac_addr) +static void wcn36xx_hw_scan_worker(struct work_struct *work) { - struct wcn36xx *wcn = hw->priv; + struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work); + struct cfg80211_scan_request *req = wcn->scan_req; + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; + struct cfg80211_scan_info scan_info = {}; + int i; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels); + + for (i = 0; i < req->n_channels; i++) + channels[i] = req->channels[i]->hw_value; + + wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels); wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); - wcn36xx_smd_start_scan(wcn); + for (i = 0; i < req->n_channels; i++) { + wcn->scan_freq = req->channels[i]->center_freq; + wcn->scan_band = req->channels[i]->band; + + wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value); + msleep(30); + wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value); + + wcn->scan_freq = 0; + } + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + + scan_info.aborted = false; + ieee80211_scan_completed(wcn->hw, &scan_info); + + mutex_lock(&wcn->scan_lock); + wcn->scan_req = NULL; + mutex_unlock(&wcn->scan_lock); } -static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int wcn36xx_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) { struct wcn36xx *wcn = hw->priv; - wcn36xx_smd_end_scan(wcn); - wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + mutex_lock(&wcn->scan_lock); + if (wcn->scan_req) { + mutex_unlock(&wcn->scan_lock); + return -EBUSY; + } + wcn->scan_req = &hw_req->req; + mutex_unlock(&wcn->scan_lock); + + schedule_work(&wcn->scan_work); + + return 0; } static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, @@ -993,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = { .configure_filter = wcn36xx_configure_filter, .tx = wcn36xx_tx, .set_key = wcn36xx_set_key, - .sw_scan_start = wcn36xx_sw_scan_start, - .sw_scan_complete = wcn36xx_sw_scan_complete, + .hw_scan = wcn36xx_hw_scan, .bss_info_changed = wcn36xx_bss_info_changed, .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, @@ -1019,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) ieee80211_hw_set(wcn->hw, SUPPORTS_PS); ieee80211_hw_set(wcn->hw, SIGNAL_DBM); ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); + ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | @@ -1028,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; + wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; + wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN; + wcn->hw->wiphy->cipher_suites = cipher_suites; wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); @@ -1058,8 +1101,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, int ret; /* Set TX IRQ */ - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "wcnss_wlantx_irq"); + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx"); if (!res) { wcn36xx_err("failed to get tx_irq\n"); return -ENOENT; @@ -1067,14 +1109,29 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, wcn->tx_irq = res->start; /* Set RX IRQ */ - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "wcnss_wlanrx_irq"); + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx"); if (!res) { wcn36xx_err("failed to get rx_irq\n"); return -ENOENT; } wcn->rx_irq = res->start; + /* Acquire SMSM tx enable handle */ + wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev, + "tx-enable", &wcn->tx_enable_state_bit); + if (IS_ERR(wcn->tx_enable_state)) { + wcn36xx_err("failed to get tx-enable state\n"); + return PTR_ERR(wcn->tx_enable_state); + } + + /* Acquire SMSM tx rings empty handle */ + wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev, + "tx-rings-empty", &wcn->tx_rings_empty_state_bit); + if (IS_ERR(wcn->tx_rings_empty_state)) { + wcn36xx_err("failed to get tx-rings-empty state\n"); + return PTR_ERR(wcn->tx_rings_empty_state); + } + mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0); if (!mmio_node) { wcn36xx_err("failed to acquire qcom,mmio reference\n"); @@ -1115,11 +1172,14 @@ static int wcn36xx_probe(struct platform_device *pdev) { struct ieee80211_hw *hw; struct wcn36xx *wcn; + void *wcnss; int ret; - u8 addr[ETH_ALEN]; + const u8 *addr; wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); + wcnss = dev_get_drvdata(pdev->dev.parent); + hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); if (!hw) { wcn36xx_err("failed to alloc hw\n"); @@ -1130,11 +1190,26 @@ static int wcn36xx_probe(struct platform_device *pdev) wcn = hw->priv; wcn->hw = hw; wcn->dev = &pdev->dev; - wcn->ctrl_ops = pdev->dev.platform_data; - mutex_init(&wcn->hal_mutex); + mutex_init(&wcn->scan_lock); + + INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); + + wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process); + if (IS_ERR(wcn->smd_channel)) { + wcn36xx_err("failed to open WLAN_CTRL channel\n"); + ret = PTR_ERR(wcn->smd_channel); + goto out_wq; + } - if (!wcn->ctrl_ops->get_hw_mac(addr)) { + qcom_smd_set_drvdata(wcn->smd_channel, hw); + + addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret); + if (addr && ret != ETH_ALEN) { + wcn36xx_err("invalid local-mac-address\n"); + ret = -EINVAL; + goto out_wq; + } else if (addr) { wcn36xx_info("mac address: %pM\n", addr); SET_IEEE80211_PERM_ADDR(wcn->hw, addr); } @@ -1158,6 +1233,7 @@ out_wq: out_err: return ret; } + static int wcn36xx_remove(struct platform_device *pdev) { struct ieee80211_hw *hw = platform_get_drvdata(pdev); @@ -1165,45 +1241,37 @@ static int wcn36xx_remove(struct platform_device *pdev) wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); release_firmware(wcn->nv); - mutex_destroy(&wcn->hal_mutex); ieee80211_unregister_hw(hw); + + qcom_smem_state_put(wcn->tx_enable_state); + qcom_smem_state_put(wcn->tx_rings_empty_state); + iounmap(wcn->dxe_base); iounmap(wcn->ccu_base); + + mutex_destroy(&wcn->hal_mutex); ieee80211_free_hw(hw); return 0; } -static const struct platform_device_id wcn36xx_platform_id_table[] = { - { - .name = "wcn36xx", - .driver_data = 0 - }, + +static const struct of_device_id wcn36xx_of_match[] = { + { .compatible = "qcom,wcnss-wlan" }, {} }; -MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); +MODULE_DEVICE_TABLE(of, wcn36xx_of_match); static struct platform_driver wcn36xx_driver = { .probe = wcn36xx_probe, .remove = wcn36xx_remove, .driver = { .name = "wcn36xx", + .of_match_table = wcn36xx_of_match, }, - .id_table = wcn36xx_platform_id_table, }; -static int __init wcn36xx_init(void) -{ - platform_driver_register(&wcn36xx_driver); - return 0; -} -module_init(wcn36xx_init); - -static void __exit wcn36xx_exit(void) -{ - platform_driver_unregister(&wcn36xx_driver); -} -module_exit(wcn36xx_exit); +module_platform_driver(wcn36xx_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index a443992320f2..1c2966f7db7a 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -19,6 +19,7 @@ #include <linux/etherdevice.h> #include <linux/firmware.h> #include <linux/bitops.h> +#include <linux/soc/qcom/smd.h> #include "smd.h" struct wcn36xx_cfg_val { @@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) init_completion(&wcn->hal_rsp_compl); start = jiffies; - ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); + ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len); if (ret) { wcn36xx_err("HAL TX failed\n"); goto out; @@ -521,7 +522,7 @@ out: return ret; } -int wcn36xx_smd_start_scan(struct wcn36xx *wcn) +int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel) { struct wcn36xx_hal_start_scan_req_msg msg_body; int ret = 0; @@ -529,7 +530,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); - msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); + msg_body.scan_channel = scan_channel; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -551,7 +552,7 @@ out: return ret; } -int wcn36xx_smd_end_scan(struct wcn36xx *wcn) +int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel) { struct wcn36xx_hal_end_scan_req_msg msg_body; int ret = 0; @@ -559,7 +560,7 @@ int wcn36xx_smd_end_scan(struct wcn36xx *wcn) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); - msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); + msg_body.scan_channel = scan_channel; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -2108,6 +2109,30 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, return -ENOENT; } +static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn, + void *buf, + size_t len) +{ + struct wcn36xx_hal_print_reg_info_ind *rsp = buf; + int i; + + if (len < sizeof(*rsp)) { + wcn36xx_warn("Corrupted print reg info indication\n"); + return -EIO; + } + + wcn36xx_dbg(WCN36XX_DBG_HAL, + "reginfo indication, scenario: 0x%x reason: 0x%x\n", + rsp->scenario, rsp->reason); + + for (i = 0; i < rsp->count; i++) { + wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n", + rsp->regs[i].addr, rsp->regs[i].value); + } + + return 0; +} + int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) { struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; @@ -2180,9 +2205,12 @@ out: return ret; } -static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) +int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel, + const void *buf, size_t len) { - struct wcn36xx_hal_msg_header *msg_header = buf; + const struct wcn36xx_hal_msg_header *msg_header = buf; + struct ieee80211_hw *hw = qcom_smd_get_drvdata(channel); + struct wcn36xx *wcn = hw->priv; struct wcn36xx_hal_ind_msg *msg_ind; wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); @@ -2233,15 +2261,12 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_OTA_TX_COMPL_IND: case WCN36XX_HAL_MISSED_BEACON_IND: case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: - msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL); + case WCN36XX_HAL_PRINT_REG_INFO_IND: + msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC); if (!msg_ind) { - /* - * FIXME: Do something smarter then just - * printing an error. - */ wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", msg_header->msg_type); - break; + return -ENOMEM; } msg_ind->msg_len = len; @@ -2257,6 +2282,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) wcn36xx_err("SMD_EVENT (%d) not supported\n", msg_header->msg_type); } + + return 0; } static void wcn36xx_ind_smd_work(struct work_struct *work) { @@ -2294,6 +2321,11 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) hal_ind_msg->msg, hal_ind_msg->msg_len); break; + case WCN36XX_HAL_PRINT_REG_INFO_IND: + wcn36xx_smd_print_reg_info_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; default: wcn36xx_err("SMD_EVENT (%d) not supported\n", msg_header->msg_type); @@ -2315,22 +2347,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn) INIT_LIST_HEAD(&wcn->hal_ind_queue); spin_lock_init(&wcn->hal_ind_lock); - ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); - if (ret) { - wcn36xx_err("failed to open control channel\n"); - goto free_wq; - } - - return ret; + return 0; -free_wq: - destroy_workqueue(wcn->hal_ind_wq); out: return ret; } void wcn36xx_smd_close(struct wcn36xx *wcn) { - wcn->ctrl_ops->close(); destroy_workqueue(wcn->hal_ind_wq); } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index df80cbbd9d1b..8892ccd67b14 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -51,6 +51,7 @@ struct wcn36xx_hal_ind_msg { }; struct wcn36xx; +struct qcom_smd_channel; int wcn36xx_smd_open(struct wcn36xx *wcn); void wcn36xx_smd_close(struct wcn36xx *wcn); @@ -59,8 +60,8 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn); int wcn36xx_smd_start(struct wcn36xx *wcn); int wcn36xx_smd_stop(struct wcn36xx *wcn); int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); -int wcn36xx_smd_start_scan(struct wcn36xx *wcn); -int wcn36xx_smd_end_scan(struct wcn36xx *wcn); +int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel); +int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel); int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count); @@ -127,6 +128,10 @@ 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_rsp_process(struct qcom_smd_channel *channel, + const void *buf, size_t len); + int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp); diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 1f34c2e912d7..8c387a0a3c09 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -45,9 +45,20 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); skb_pull(skb, bd->pdu.mpdu_header_off); + hdr = (struct ieee80211_hdr *) skb->data; + fc = __le16_to_cpu(hdr->frame_control); + sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); + + /* When scanning associate beacons to this */ + if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) { + status.freq = wcn->scan_freq; + status.band = wcn->scan_band; + } else { + status.freq = WCN36XX_CENTER_FREQ(wcn); + status.band = WCN36XX_BAND(wcn); + } + status.mactime = 10; - status.freq = WCN36XX_CENTER_FREQ(wcn); - status.band = WCN36XX_BAND(wcn); status.signal = -get_rssi0(bd); status.antenna = 1; status.rate_idx = 1; @@ -61,10 +72,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - hdr = (struct ieee80211_hdr *) skb->data; - fc = __le16_to_cpu(hdr->frame_control); - sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); - if (ieee80211_is_beacon(hdr->frame_control)) { wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", skb, skb->len, fc, sn); diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 22242d18e1fe..35a6590c3ee5 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -35,6 +35,9 @@ /* How many frames until we start a-mpdu TX session */ #define WCN36XX_AMPDU_START_THRESH 20 +#define WCN36XX_MAX_SCAN_SSIDS 9 +#define WCN36XX_MAX_SCAN_IE_LEN 500 + extern unsigned int wcn36xx_dbg_mask; enum wcn36xx_debug_mask { @@ -103,19 +106,6 @@ struct nv_data { u8 table; }; -/* Interface for platform control path - * - * @open: hook must be called when wcn36xx wants to open control channel. - * @tx: sends a buffer. - */ -struct wcn36xx_platform_ctrl_ops { - int (*open)(void *drv_priv, void *rsp_cb); - void (*close)(void); - int (*tx)(char *buf, size_t len); - int (*get_hw_mac)(u8 *addr); - int (*smsm_change_state)(u32 clear_mask, u32 set_mask); -}; - /** * struct wcn36xx_vif - holds VIF related fields * @@ -205,7 +195,13 @@ struct wcn36xx { void __iomem *ccu_base; void __iomem *dxe_base; - struct wcn36xx_platform_ctrl_ops *ctrl_ops; + struct qcom_smd_channel *smd_channel; + + struct qcom_smem_state *tx_enable_state; + unsigned tx_enable_state_bit; + struct qcom_smem_state *tx_rings_empty_state; + unsigned tx_rings_empty_state_bit; + /* * smd_buf must be protected with smd_mutex to garantee * that all messages are sent one after another @@ -219,6 +215,12 @@ struct wcn36xx { spinlock_t hal_ind_lock; struct list_head hal_ind_queue; + struct work_struct scan_work; + struct cfg80211_scan_request *scan_req; + int scan_freq; + int scan_band; + struct mutex scan_lock; + /* DXE channels */ struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 6aa3ff4240a9..e25e78e71f54 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,6 +20,10 @@ #define WIL_MAX_ROC_DURATION_MS 5000 +bool disable_ap_sme; +module_param(disable_ap_sme, bool, 0444); +MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME"); + #define CHAN60G(_channel, _flags) { \ .band = NL80211_BAND_60GHZ, \ .center_freq = 56160 + (2160 * (_channel)), \ @@ -62,9 +66,16 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_AP] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | + BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) }, [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | @@ -194,7 +205,7 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy, int cid = wil_find_cid(wil, mac); - wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); + wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid); if (cid < 0) return cid; @@ -233,7 +244,7 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, return -ENOENT; ether_addr_copy(mac, wil->sta[cid].addr); - wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); + wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid); rc = wil_cid_fill_sinfo(wil, cid, sinfo); @@ -250,16 +261,15 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *p2p_wdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "add_iface\n"); if (type != NL80211_IFTYPE_P2P_DEVICE) { - wil_err(wil, "%s: unsupported iftype %d\n", __func__, type); + wil_err(wil, "unsupported iftype %d\n", type); return ERR_PTR(-EINVAL); } if (wil->p2p_wdev) { - wil_err(wil, "%s: P2P_DEVICE interface already created\n", - __func__); + wil_err(wil, "P2P_DEVICE interface already created\n"); return ERR_PTR(-EINVAL); } @@ -282,11 +292,10 @@ static int wil_cfg80211_del_iface(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "del_iface\n"); if (wdev != wil->p2p_wdev) { - wil_err(wil, "%s: delete of incorrect interface 0x%p\n", - __func__, wdev); + wil_err(wil, "delete of incorrect interface 0x%p\n", wdev); return -EINVAL; } @@ -304,7 +313,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, struct wireless_dev *wdev = wil_to_wdev(wil); int rc; - wil_dbg_misc(wil, "%s() type=%d\n", __func__, type); + wil_dbg_misc(wil, "change_iface: type=%d\n", type); if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) { wil_dbg_misc(wil, "interface is up. resetting...\n"); @@ -351,8 +360,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, uint i, n; int rc; - wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", - __func__, wdev, wdev->iftype); + wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype); /* check we are client side */ switch (wdev->iftype) { @@ -557,7 +565,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, int rc = 0; enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "connect\n"); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || @@ -593,6 +601,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, goto out; } wil->privacy = sme->privacy; + wil->pbss = sme->pbss; if (wil->privacy) { /* For secure assoc, remove old keys */ @@ -689,12 +698,11 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); + wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code); if (!(test_bit(wil_status_fwconnecting, wil->status) || test_bit(wil_status_fwconnected, wil->status))) { - wil_err(wil, "%s: Disconnect was called while disconnected\n", - __func__); + wil_err(wil, "Disconnect was called while disconnected\n"); return 0; } @@ -702,7 +710,7 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, WMI_DISCONNECT_EVENTID, NULL, 0, WIL6210_DISCONNECT_TO_MS); if (rc) - wil_err(wil, "%s: disconnect error %d\n", __func__, rc); + wil_err(wil, "disconnect error %d\n", rc); return rc; } @@ -750,7 +758,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * different from currently "listened" channel and fail if it is. */ - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "mgmt_tx\n"); print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len); cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); @@ -811,7 +819,7 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, break; } } - wil_dbg_misc(wil, "%s() -> %s\n", __func__, key_usage_str[rc]); + wil_dbg_misc(wil, "detect_key_usage: -> %s\n", key_usage_str[rc]); return rc; } @@ -916,13 +924,13 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, return -EINVAL; } - wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__, + wil_dbg_misc(wil, "add_key: %pM %s[%d] PN %*phN\n", mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); if (IS_ERR(cs)) { - wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n", - __func__, mac_addr, key_usage_str[key_usage], key_index, + wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n", + mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); return -EINVAL; } @@ -931,8 +939,8 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { wil_err(wil, - "Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n", - params->seq_len, __func__, mac_addr, + "Wrong PN len %d, %pM %s[%d] PN %*phN\n", + params->seq_len, mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); return -EINVAL; @@ -956,11 +964,11 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, mac_addr); - wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr, + wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr, key_usage_str[key_usage], key_index); if (IS_ERR(cs)) - wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__, + wil_info(wil, "Not connected, %pM %s[%d]\n", mac_addr, key_usage_str[key_usage], key_index); if (!IS_ERR_OR_NULL(cs)) @@ -977,7 +985,7 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "set_default_key: entered\n"); return 0; } @@ -990,8 +998,9 @@ static int wil_remain_on_channel(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n", - __func__, chan->center_freq, duration, wdev->iftype); + wil_dbg_misc(wil, + "remain_on_channel: center_freq=%d, duration=%d iftype=%d\n", + chan->center_freq, duration, wdev->iftype); rc = wil_p2p_listen(wil, wdev, duration, chan, cookie); return rc; @@ -1003,7 +1012,7 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "cancel_remain_on_channel\n"); return wil_p2p_cancel_listen(wil, cookie); } @@ -1159,9 +1168,9 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (pbss) wmi_nettype = WMI_NETTYPE_P2P; - wil_dbg_misc(wil, "%s: is_go=%d\n", __func__, is_go); + wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go); if (is_go && !pbss) { - wil_err(wil, "%s: P2P GO must be in PBSS\n", __func__); + wil_err(wil, "P2P GO must be in PBSS\n"); return -ENOTSUPP; } @@ -1216,7 +1225,7 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, int rc; u32 privacy = 0; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "change_beacon\n"); wil_print_bcon_data(bcon); if (bcon->tail && @@ -1255,7 +1264,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, struct cfg80211_crypto_settings *crypto = &info->crypto; u8 hidden_ssid; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "start_ap\n"); if (!channel) { wil_err(wil, "AP: No channel???\n"); @@ -1306,7 +1315,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "stop_ap\n"); netif_carrier_off(ndev); wil_set_recovery_state(wil, fw_recovery_idle); @@ -1322,13 +1331,35 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid); + + if (!disable_ap_sme) { + wil_err(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (params->aid > WIL_MAX_DMG_AID) { + wil_err(wil, "invalid aid\n"); + return -EINVAL; + } + + return wmi_new_sta(wil, mac, params->aid); +} + static int wil_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s(%pM, reason=%d)\n", __func__, params->mac, + wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac, params->reason_code); mutex_lock(&wil->mutex); @@ -1338,6 +1369,52 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int authorize; + int cid, i; + struct vring_tx_data *txdata = NULL; + + wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac, + params->sta_flags_mask, params->sta_flags_set); + + if (!disable_ap_sme) { + wil_dbg_misc(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + return 0; + + cid = wil_find_cid(wil, mac); + if (cid < 0) { + wil_err(wil, "station not found\n"); + return -ENOLINK; + } + + for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) + if (wil->vring2cid_tid[i][0] == cid) { + txdata = &wil->vring_tx_data[i]; + break; + } + + if (!txdata) { + wil_err(wil, "vring data not found\n"); + return -ENOLINK; + } + + authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); + txdata->dot1x_open = authorize ? 1 : 0; + wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i, + txdata->dot1x_open); + + return 0; +} + /* probe_client handling */ static void wil_probe_client_handle(struct wil6210_priv *wil, struct wil_probe_client_req *req) @@ -1387,7 +1464,7 @@ void wil_probe_client_flush(struct wil6210_priv *wil) { struct wil_probe_client_req *req, *t; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "probe_client_flush\n"); mutex_lock(&wil->probe_client_mutex); @@ -1407,7 +1484,7 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, struct wil_probe_client_req *req; int cid = wil_find_cid(wil, peer); - wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid); + wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid); if (cid < 0) return -ENOLINK; @@ -1435,7 +1512,7 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); if (params->ap_isolate >= 0) { - wil_dbg_misc(wil, "%s(ap_isolate %d => %d)\n", __func__, + wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n", wil->ap_isolate, params->ap_isolate); wil->ap_isolate = params->ap_isolate; } @@ -1448,7 +1525,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "start_p2p_device: entered\n"); wil->p2p.p2p_dev_started = 1; return 0; } @@ -1462,7 +1539,7 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, if (!p2p->p2p_dev_started) return; - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "stop_p2p_device: entered\n"); mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); wil_p2p_stop_radio_operations(wil); @@ -1499,7 +1576,7 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy, return rc; } -static struct cfg80211_ops wil_cfg80211_ops = { +static const struct cfg80211_ops wil_cfg80211_ops = { .add_virtual_intf = wil_cfg80211_add_iface, .del_virtual_intf = wil_cfg80211_del_iface, .scan = wil_cfg80211_scan, @@ -1521,7 +1598,9 @@ static struct cfg80211_ops wil_cfg80211_ops = { .change_beacon = wil_cfg80211_change_beacon, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, + .add_station = wil_cfg80211_add_station, .del_station = wil_cfg80211_del_station, + .change_station = wil_cfg80211_change_station, .probe_client = wil_cfg80211_probe_client, .change_bss = wil_cfg80211_change_bss, /* P2P device */ @@ -1542,10 +1621,11 @@ static void wil_wiphy_init(struct wiphy *wiphy) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_MONITOR); - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_PS_ON_BY_DEFAULT; + if (!disable_ap_sme) + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); wiphy->probe_resp_offload = diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 5e4058a4037b..3e8cdf12feda 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -364,13 +364,13 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, } static const struct dbg_off isr_off[] = { - {"ICC", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICC), doff_io32}, - {"ICR", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICR), doff_io32}, - {"ICM", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICM), doff_io32}, - {"ICS", S_IWUSR, offsetof(struct RGF_ICR, ICS), doff_io32}, - {"IMV", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, IMV), doff_io32}, - {"IMS", S_IWUSR, offsetof(struct RGF_ICR, IMS), doff_io32}, - {"IMC", S_IWUSR, offsetof(struct RGF_ICR, IMC), doff_io32}, + {"ICC", 0644, offsetof(struct RGF_ICR, ICC), doff_io32}, + {"ICR", 0644, offsetof(struct RGF_ICR, ICR), doff_io32}, + {"ICM", 0644, offsetof(struct RGF_ICR, ICM), doff_io32}, + {"ICS", 0244, offsetof(struct RGF_ICR, ICS), doff_io32}, + {"IMV", 0644, offsetof(struct RGF_ICR, IMV), doff_io32}, + {"IMS", 0244, offsetof(struct RGF_ICR, IMS), doff_io32}, + {"IMC", 0244, offsetof(struct RGF_ICR, IMC), doff_io32}, {}, }; @@ -390,9 +390,9 @@ static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, } static const struct dbg_off pseudo_isr_off[] = { - {"CAUSE", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, - {"MASK_SW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, - {"MASK_FW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, + {"CAUSE", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, + {"MASK_SW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, + {"MASK_FW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, {}, }; @@ -411,40 +411,40 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, } static const struct dbg_off lgc_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, {}, }; static const struct dbg_off tx_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), doff_io32}, - {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), + {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), doff_io32}, - {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), + {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), doff_io32}, - {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), + {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), doff_io32}, {}, }; static const struct dbg_off rx_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), doff_io32}, - {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), + {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), doff_io32}, - {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), + {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), doff_io32}, - {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), + {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), doff_io32}, {}, }; @@ -813,7 +813,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, rc = wil_cfg80211_mgmt_tx(wiphy, wdev, ¶ms, NULL); kfree(frame); - wil_info(wil, "%s() -> %d\n", __func__, rc); + wil_info(wil, "-> %d\n", rc); return len; } @@ -855,7 +855,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, rc1 = wmi_send(wil, cmdid, cmd, cmdlen); kfree(wmi); - wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1); + wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); return rc; } @@ -1379,6 +1379,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; + u8 aid = 0; switch (p->status) { case wil_sta_unused: @@ -1389,9 +1390,10 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) break; case wil_sta_connected: status = "connected"; + aid = p->aid; break; } - seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); + seq_printf(s, "[%d] %pM %s AID %d\n", i, p->addr, status, aid); if (p->status == wil_sta_connected) { spin_lock_bh(&p->tid_rx_lock); @@ -1622,7 +1624,7 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, blob->data = (void * __force)wil->csr + HOSTADDR(map->host); blob->size = map->to - map->from; snprintf(name, sizeof(name), "blob_%s", map->name); - wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob); + wil_debugfs_create_ioblob(name, 0444, dbg, wil_blob); } } @@ -1632,29 +1634,29 @@ static const struct { umode_t mode; const struct file_operations *fops; } dbg_files[] = { - {"mbox", S_IRUGO, &fops_mbox}, - {"vrings", S_IRUGO, &fops_vring}, - {"stations", S_IRUGO, &fops_sta}, - {"desc", S_IRUGO, &fops_txdesc}, - {"bf", S_IRUGO, &fops_bf}, - {"ssid", S_IRUGO | S_IWUSR, &fops_ssid}, - {"mem_val", S_IRUGO, &fops_memread}, - {"reset", S_IWUSR, &fops_reset}, - {"rxon", S_IWUSR, &fops_rxon}, - {"tx_mgmt", S_IWUSR, &fops_txmgmt}, - {"wmi_send", S_IWUSR, &fops_wmi}, - {"back", S_IRUGO | S_IWUSR, &fops_back}, - {"pmccfg", S_IRUGO | S_IWUSR, &fops_pmccfg}, - {"pmcdata", S_IRUGO, &fops_pmcdata}, - {"temp", S_IRUGO, &fops_temp}, - {"freq", S_IRUGO, &fops_freq}, - {"link", S_IRUGO, &fops_link}, - {"info", S_IRUGO, &fops_info}, - {"recovery", S_IRUGO | S_IWUSR, &fops_recovery}, - {"led_cfg", S_IRUGO | S_IWUSR, &fops_led_cfg}, - {"led_blink_time", S_IRUGO | S_IWUSR, &fops_led_blink_time}, - {"fw_capabilities", S_IRUGO, &fops_fw_capabilities}, - {"fw_version", S_IRUGO, &fops_fw_version}, + {"mbox", 0444, &fops_mbox}, + {"vrings", 0444, &fops_vring}, + {"stations", 0444, &fops_sta}, + {"desc", 0444, &fops_txdesc}, + {"bf", 0444, &fops_bf}, + {"ssid", 0644, &fops_ssid}, + {"mem_val", 0644, &fops_memread}, + {"reset", 0244, &fops_reset}, + {"rxon", 0244, &fops_rxon}, + {"tx_mgmt", 0244, &fops_txmgmt}, + {"wmi_send", 0244, &fops_wmi}, + {"back", 0644, &fops_back}, + {"pmccfg", 0644, &fops_pmccfg}, + {"pmcdata", 0444, &fops_pmcdata}, + {"temp", 0444, &fops_temp}, + {"freq", 0444, &fops_freq}, + {"link", 0444, &fops_link}, + {"info", 0444, &fops_info}, + {"recovery", 0644, &fops_recovery}, + {"led_cfg", 0644, &fops_led_cfg}, + {"led_blink_time", 0644, &fops_led_blink_time}, + {"fw_capabilities", 0444, &fops_fw_capabilities}, + {"fw_version", 0444, &fops_fw_version}, }; static void wil6210_debugfs_init_files(struct wil6210_priv *wil, @@ -1693,30 +1695,32 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, /* fields in struct wil6210_priv */ static const struct dbg_off dbg_wil_off[] = { - WIL_FIELD(privacy, S_IRUGO, doff_u32), - WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong), - WIL_FIELD(hw_version, S_IRUGO, doff_x32), - WIL_FIELD(recovery_count, S_IRUGO, doff_u32), - WIL_FIELD(ap_isolate, S_IRUGO, doff_u32), - WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR, doff_u8), + WIL_FIELD(privacy, 0444, doff_u32), + WIL_FIELD(status[0], 0644, doff_ulong), + WIL_FIELD(hw_version, 0444, doff_x32), + WIL_FIELD(recovery_count, 0444, doff_u32), + WIL_FIELD(ap_isolate, 0444, doff_u32), + WIL_FIELD(discovery_mode, 0644, doff_u8), + WIL_FIELD(chip_revision, 0444, doff_u8), + WIL_FIELD(abft_len, 0644, doff_u8), {}, }; static const struct dbg_off dbg_wil_regs[] = { - {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), + {"RGF_MAC_MTRL_COUNTER_0", 0444, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), doff_io32}, - {"RGF_USER_USAGE_1", S_IRUGO, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, + {"RGF_USER_USAGE_1", 0444, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, {}, }; /* static parameters */ static const struct dbg_off dbg_statics[] = { - {"desc_index", S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32}, - {"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32}, - {"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32}, - {"vring_idle_trsh", S_IRUGO | S_IWUSR, (ulong)&vring_idle_trsh, + {"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32}, + {"vring_index", 0644, (ulong)&dbg_vring_index, doff_u32}, + {"mem_addr", 0644, (ulong)&mem_addr, doff_u32}, + {"vring_idle_trsh", 0644, (ulong)&vring_idle_trsh, doff_u32}, - {"led_polarity", S_IRUGO | S_IWUSR, (ulong)&led_polarity, doff_u8}, + {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, {}, }; diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c index 7053b62ca8d3..adcfef4dabf7 100644 --- a/drivers/net/wireless/ath/wil6210/ethtool.c +++ b/drivers/net/wireless/ath/wil6210/ethtool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Qualcomm Atheros, Inc. + * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,7 @@ static int wil_ethtoolops_begin(struct net_device *ndev) mutex_lock(&wil->mutex); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_begin\n"); return 0; } @@ -36,7 +36,7 @@ static void wil_ethtoolops_complete(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_complete\n"); mutex_unlock(&wil->mutex); } @@ -48,7 +48,7 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev, u32 tx_itr_en, tx_itr_val = 0; u32 rx_itr_en, rx_itr_val = 0; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_get_coalesce\n"); tx_itr_en = wil_r(wil, RGF_DMA_ITR_TX_CNT_CTL); if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN) @@ -68,7 +68,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev, { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s(rx %d usec, tx %d usec)\n", __func__, + wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n", cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c index 82aae2d705b4..540fc20984d8 100644 --- a/drivers/net/wireless/ath/wil6210/fw.c +++ b/drivers/net/wireless/ath/wil6210/fw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,8 +19,9 @@ #include "wil6210.h" #include "fw.h" -MODULE_FIRMWARE(WIL_FW_NAME); -MODULE_FIRMWARE(WIL_FW2_NAME); +MODULE_FIRMWARE(WIL_FW_NAME_DEFAULT); +MODULE_FIRMWARE(WIL_FW_NAME_SPARROW_PLUS); +MODULE_FIRMWARE(WIL_BOARD_FILE_NAME); static void wil_memset_toio_32(volatile void __iomem *dst, u32 val, diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 8f40eb301924..f4901587c005 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -537,3 +537,22 @@ out: release_firmware(fw); return rc; } + +/** + * wil_fw_verify_file_exists - checks if firmware file exist + * + * @wil: driver context + * @name: firmware file name + * + * return value - boolean, true for success, false for failure + */ +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name) +{ + const struct firmware *fw; + int rc; + + rc = request_firmware(&fw, name, wil_to_dev(wil)); + if (!rc) + release_firmware(fw); + return rc != -ENOENT; +} diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 64046e0bd0a2..cab1e5c0e374 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -94,7 +94,7 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil) static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) { - wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__, + wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n", mask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), @@ -103,7 +103,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) void wil6210_mask_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), BIT_DMA_EP_MISC_ICR_HALP); @@ -111,7 +111,7 @@ void wil6210_mask_halp(struct wil6210_priv *wil) static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_irq_pseudo\n"); wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_DISABLE); @@ -134,7 +134,7 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil) static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) { - wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__, + wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n", unmask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), @@ -143,7 +143,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) static void wil6210_unmask_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), BIT_DMA_EP_MISC_ICR_HALP); @@ -151,7 +151,7 @@ static void wil6210_unmask_halp(struct wil6210_priv *wil) static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_irq_pseudo\n"); set_bit(wil_status_irqen, wil->status); @@ -160,7 +160,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) void wil_mask_irq(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_irq\n"); wil6210_mask_irq_tx(wil); wil6210_mask_irq_rx(wil); @@ -170,7 +170,7 @@ void wil_mask_irq(struct wil6210_priv *wil) void wil_unmask_irq(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_irq\n"); wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); @@ -187,7 +187,7 @@ void wil_unmask_irq(struct wil6210_priv *wil) void wil_configure_interrupt_moderation(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "configure_interrupt_moderation\n"); /* disable interrupt moderation for monitor * to get better timestamp precision @@ -400,7 +400,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { - wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__); + wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; complete(&wil->halp.comp); @@ -599,7 +599,7 @@ void wil6210_clear_irq(struct wil6210_priv *wil) void wil6210_set_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "set_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), BIT_DMA_EP_MISC_ICR_HALP); @@ -607,7 +607,7 @@ void wil6210_set_halp(struct wil6210_priv *wil) void wil6210_clear_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "clear_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), BIT_DMA_EP_MISC_ICR_HALP); @@ -618,7 +618,7 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) { int rc; - wil_dbg_misc(wil, "%s(%s)\n", __func__, use_msi ? "MSI" : "INTx"); + wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx"); rc = request_threaded_irq(irq, wil6210_hardirq, wil6210_thread_irq, @@ -629,7 +629,7 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) void wil6210_fini_irq(struct wil6210_priv *wil, int irq) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "fini_irq:\n"); wil_mask_irq(wil); free_irq(irq, wil); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index e2e021bcaa03..efb1f59aafd9 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,23 +27,23 @@ #define WAIT_FOR_SCAN_ABORT_MS 1000 bool debug_fw; /* = false; */ -module_param(debug_fw, bool, S_IRUGO); +module_param(debug_fw, bool, 0444); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); static bool oob_mode; -module_param(oob_mode, bool, S_IRUGO); +module_param(oob_mode, bool, 0444); MODULE_PARM_DESC(oob_mode, " enable out of the box (OOB) mode in FW, for diagnostics and certification"); bool no_fw_recovery; -module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); +module_param(no_fw_recovery, bool, 0644); MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery"); /* if not set via modparam, will be set to default value of 1/8 of * rx ring size during init flow */ unsigned short rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_INIT; -module_param(rx_ring_overflow_thrsh, ushort, S_IRUGO); +module_param(rx_ring_overflow_thrsh, ushort, 0444); MODULE_PARM_DESC(rx_ring_overflow_thrsh, " RX ring overflow threshold in descriptors."); @@ -73,7 +73,7 @@ static const struct kernel_param_ops mtu_max_ops = { .get = param_get_uint, }; -module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); +module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, 0444); MODULE_PARM_DESC(mtu_max, " Max MTU value."); static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT; @@ -102,11 +102,11 @@ static const struct kernel_param_ops ring_order_ops = { .get = param_get_uint, }; -module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO); +module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, 0444); MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); -module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); +module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, 0444); MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order"); -module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO); +module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444); MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order"); #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ @@ -172,12 +172,16 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) struct wil_sta_info *sta = &wil->sta[cid]; might_sleep(); - wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, - sta->status); + wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n", + cid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { - if (!from_event) - wmi_disconnect_sta(wil, sta->addr, reason_code, true); + if (!from_event) { + bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? + disable_ap_sme : false; + wmi_disconnect_sta(wil, sta->addr, reason_code, + true, del_sta); + } switch (wdev->iftype) { case NL80211_IFTYPE_AP: @@ -237,7 +241,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, return; might_sleep(); - wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, + wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid, reason_code, from_event ? "+" : "-"); /* Cases are: @@ -347,7 +351,7 @@ static int wil_wait_for_recovery(struct wil6210_priv *wil) void wil_set_recovery_state(struct wil6210_priv *wil, int state) { - wil_dbg_misc(wil, "%s(%d -> %d)\n", __func__, + wil_dbg_misc(wil, "set_recovery_state: %d -> %d\n", wil->recovery_state, state); wil->recovery_state = state; @@ -489,7 +493,7 @@ int wil_priv_init(struct wil6210_priv *wil) { uint i; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "priv_init\n"); memset(wil->sta, 0, sizeof(wil->sta)); for (i = 0; i < WIL6210_MAX_CID; i++) @@ -564,7 +568,7 @@ out_wmi_wq: void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "disconnect\n"); del_timer_sync(&wil->connect_timer); _wil6210_disconnect(wil, bssid, reason_code, from_event); @@ -572,7 +576,7 @@ void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, void wil_priv_deinit(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "priv_deinit\n"); wil_set_recovery_state(wil, fw_recovery_idle); del_timer_sync(&wil->scan_timer); @@ -605,7 +609,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) { - wil_info(wil, "%s: enable=%d\n", __func__, enable); + wil_info(wil, "enable=%d\n", enable); if (enable) wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); else @@ -861,7 +865,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "reset\n"); WARN_ON(!mutex_is_locked(&wil->mutex)); WARN_ON(test_bit(wil_status_napi_en, wil->status)); @@ -884,9 +888,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_PRE_RESET); if (rc) - wil_err(wil, - "%s: PRE_RESET platform notify failed, rc %d\n", - __func__, rc); + wil_err(wil, "PRE_RESET platform notify failed, rc %d\n", + rc); } set_bit(wil_status_resetting, wil->status); @@ -915,7 +918,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) flush_workqueue(wil->wmi_wq); wil_bl_crash_info(wil, false); + wil_disable_irq(wil); rc = wil_target_reset(wil); + wil6210_clear_irq(wil); + wil_enable_irq(wil); wil_rx_fini(wil); if (rc) { wil_bl_crash_info(wil, true); @@ -930,16 +936,16 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil_set_oob_mode(wil, oob_mode); if (load_fw) { - wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME, - WIL_FW2_NAME); + wil_info(wil, "Use firmware <%s> + board <%s>\n", + wil->wil_fw_name, WIL_BOARD_FILE_NAME); wil_halt_cpu(wil); memset(wil->fw_version, 0, sizeof(wil->fw_version)); /* Loading f/w from the file */ - rc = wil_request_firmware(wil, WIL_FW_NAME, true); + rc = wil_request_firmware(wil, wil->wil_fw_name, true); if (rc) return rc; - rc = wil_request_firmware(wil, WIL_FW2_NAME, true); + rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true); if (rc) return rc; @@ -976,8 +982,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) /* check FW is responsive */ rc = wmi_echo(wil); if (rc) { - wil_err(wil, "%s: wmi_echo failed, rc %d\n", - __func__, rc); + wil_err(wil, "wmi_echo failed, rc %d\n", rc); return rc; } @@ -987,9 +992,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_FW_RDY); if (rc) { - wil_err(wil, - "%s: FW_RDY notify failed, rc %d\n", - __func__, rc); + wil_err(wil, "FW_RDY notify failed, rc %d\n", + rc); rc = 0; } } @@ -1073,7 +1077,7 @@ int wil_up(struct wil6210_priv *wil) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "up\n"); mutex_lock(&wil->mutex); rc = __wil_up(wil); @@ -1113,7 +1117,7 @@ int wil_down(struct wil6210_priv *wil) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "down\n"); wil_set_recovery_state(wil, fw_recovery_idle); mutex_lock(&wil->mutex); @@ -1146,25 +1150,24 @@ void wil_halp_vote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_vote: start, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); if (++wil->halp.ref_cnt == 1) { wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) { - wil_err(wil, "%s: HALP vote timed out\n", __func__); + wil_err(wil, "HALP vote timed out\n"); /* Mask HALP as done in case the interrupt is raised */ wil6210_mask_halp(wil); } else { wil_dbg_irq(wil, - "%s: HALP vote completed after %d ms\n", - __func__, + "halp_vote: HALP vote completed after %d ms\n", jiffies_to_msecs(to_jiffies - rc)); } } - wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_vote: end, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); @@ -1176,15 +1179,15 @@ void wil_halp_unvote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_unvote: start, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); if (--wil->halp.ref_cnt == 0) { wil6210_clear_halp(wil); - wil_dbg_irq(wil, "%s: HALP unvote\n", __func__); + wil_dbg_irq(wil, "HALP unvote\n"); } - wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_unvote:end, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index cab5334e4f9d..708facd5f667 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,10 +22,11 @@ static int wil_open(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "open\n"); - if (debug_fw) { - wil_err(wil, "%s() while in debug_fw mode\n", __func__); + if (debug_fw || + test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) { + wil_err(wil, "while in debug_fw or wmi_only mode\n"); return -EINVAL; } @@ -36,7 +37,7 @@ static int wil_stop(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "stop\n"); return wil_down(wil); } @@ -132,7 +133,7 @@ void *wil_if_alloc(struct device *dev) wil->wdev = wdev; wil->radio_wdev = wdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_alloc\n"); rc = wil_priv_init(wil); if (rc) { @@ -179,7 +180,7 @@ void wil_if_free(struct wil6210_priv *wil) { struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_free\n"); if (!ndev) return; @@ -234,7 +235,7 @@ void wil_if_remove(struct wil6210_priv *wil) struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *wdev = wil_to_wdev(wil); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_remove\n"); unregister_netdev(ndev); wiphy_unregister(wdev->wiphy); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index fbae99525e01..792484756654 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -69,7 +69,7 @@ void wil_p2p_discovery_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; - wil_dbg_misc(wil, "%s\n", __func__); + wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); schedule_work(&wil->p2p.discovery_expired_work); } @@ -80,27 +80,25 @@ int wil_p2p_search(struct wil6210_priv *wil, int rc; struct wil_p2p_info *p2p = &wil->p2p; - wil_dbg_misc(wil, "%s: channel %d\n", - __func__, P2P_DMG_SOCIAL_CHANNEL); + wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL); lockdep_assert_held(&wil->mutex); if (p2p->discovery_started) { - wil_err(wil, "%s: search failed. discovery already ongoing\n", - __func__); + wil_err(wil, "search failed. discovery already ongoing\n"); rc = -EBUSY; goto out; } rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); if (rc) { - wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); + wil_err(wil, "wmi_p2p_cfg failed\n"); goto out; } rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); if (rc) { - wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); + wil_err(wil, "wmi_set_ssid failed\n"); goto out_stop; } @@ -108,8 +106,7 @@ int wil_p2p_search(struct wil6210_priv *wil, rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); if (rc) { - wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n", - __func__); + wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n"); goto out_stop; } @@ -119,14 +116,13 @@ int wil_p2p_search(struct wil6210_priv *wil, rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, request->ie_len, request->ie); if (rc) { - wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n", - __func__); + wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n"); goto out_stop; } rc = wmi_start_search(wil); if (rc) { - wil_err(wil, "%s: wmi_start_search failed\n", __func__); + wil_err(wil, "wmi_start_search failed\n"); goto out_stop; } @@ -153,12 +149,12 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, if (!chan) return -EINVAL; - wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration); + wil_dbg_misc(wil, "p2p_listen: duration %d\n", duration); mutex_lock(&wil->mutex); if (p2p->discovery_started) { - wil_err(wil, "%s: discovery already ongoing\n", __func__); + wil_err(wil, "discovery already ongoing\n"); rc = -EBUSY; goto out; } @@ -220,8 +216,8 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) mutex_lock(&wil->mutex); if (cookie != p2p->cookie) { - wil_info(wil, "%s: Cookie mismatch: 0x%016llx vs. 0x%016llx\n", - __func__, p2p->cookie, cookie); + wil_info(wil, "Cookie mismatch: 0x%016llx vs. 0x%016llx\n", + p2p->cookie, cookie); mutex_unlock(&wil->mutex); return -ENOENT; } @@ -231,7 +227,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) mutex_unlock(&wil->mutex); if (!started) { - wil_err(wil, "%s: listen not started\n", __func__); + wil_err(wil, "listen not started\n"); return -ENOENT; } @@ -253,7 +249,7 @@ void wil_p2p_listen_expired(struct work_struct *work) struct wil6210_priv, p2p); u8 started; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "p2p_listen_expired\n"); mutex_lock(&wil->mutex); started = wil_p2p_stop_discovery(wil); @@ -279,7 +275,7 @@ void wil_p2p_search_expired(struct work_struct *work) struct wil6210_priv, p2p); u8 started; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "p2p_search_expired\n"); mutex_lock(&wil->mutex); started = wil_p2p_stop_discovery(wil); diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 44746ca0d2e6..874c787727fe 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -23,7 +23,7 @@ #include <linux/rtnetlink.h> static bool use_msi = true; -module_param(use_msi, bool, S_IRUGO); +module_param(use_msi, bool, 0444); MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true"); #ifdef CONFIG_PM @@ -36,18 +36,38 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, static void wil_set_capabilities(struct wil6210_priv *wil) { - u32 rev_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & + RGF_USER_REVISION_ID_MASK); bitmap_zero(wil->hw_capabilities, hw_capability_last); bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); - - switch (rev_id) { - case JTAG_DEV_ID_SPARROW_B0: - wil->hw_name = "Sparrow B0"; - wil->hw_version = HW_VER_SPARROW_B0; + wil->wil_fw_name = WIL_FW_NAME_DEFAULT; + wil->chip_revision = chip_revision; + + switch (jtag_id) { + case JTAG_DEV_ID_SPARROW: + switch (chip_revision) { + case REVISION_ID_SPARROW_D0: + wil->hw_name = "Sparrow D0"; + wil->hw_version = HW_VER_SPARROW_D0; + if (wil_fw_verify_file_exists(wil, + WIL_FW_NAME_SPARROW_PLUS)) + wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS; + break; + case REVISION_ID_SPARROW_B0: + wil->hw_name = "Sparrow B0"; + wil->hw_version = HW_VER_SPARROW_B0; + break; + default: + wil->hw_name = "Unknown"; + wil->hw_version = HW_VER_UNKNOWN; + break; + } break; default: - wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id); + wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", + jtag_id, chip_revision); wil->hw_name = "Unknown"; wil->hw_version = HW_VER_UNKNOWN; } @@ -55,7 +75,7 @@ void wil_set_capabilities(struct wil6210_priv *wil) wil_info(wil, "Board hardware is %s\n", wil->hw_name); /* extract FW capabilities from file without loading the FW */ - wil_request_firmware(wil, WIL_FW_NAME, false); + wil_request_firmware(wil, wil->wil_fw_name, false); } void wil_disable_irq(struct wil6210_priv *wil) @@ -79,8 +99,10 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) */ int msi_only = pdev->msi_enabled; bool _use_msi = use_msi; + bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, + wil->fw_capabilities); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only); pdev->msi_enabled = 0; @@ -103,9 +125,11 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) if (rc) goto stop_master; - /* need reset here to obtain MAC */ + /* need reset here to obtain MAC or in case of WMI-only FW, full reset + * and fw loading takes place + */ mutex_lock(&wil->mutex); - rc = wil_reset(wil, false); + rc = wil_reset(wil, wmi_only); mutex_unlock(&wil->mutex); if (rc) goto release_irq; @@ -125,7 +149,7 @@ static int wil_if_pcie_disable(struct wil6210_priv *wil) { struct pci_dev *pdev = wil->pdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_pcie_disable\n"); pci_clear_master(pdev); /* disable and release IRQ */ @@ -289,7 +313,7 @@ static void wil_pcie_remove(struct pci_dev *pdev) struct wil6210_priv *wil = pci_get_drvdata(pdev); void __iomem *csr = wil->csr; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "pcie_remove\n"); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP @@ -327,8 +351,7 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); rc = wil_can_suspend(wil, is_runtime); if (rc) @@ -354,8 +377,7 @@ static int wil6210_resume(struct device *dev, bool is_runtime) struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); /* allow master */ pci_set_master(pdev); @@ -375,7 +397,7 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, int rc = 0; enum wil_platform_event evt; - wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode); + wil_dbg_pm(wil, "pm_notify: mode (%ld)\n", mode); switch (mode) { case PM_HIBERNATION_PREPARE: diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 11ee24d509e5..a0acb2d0cb79 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,8 +21,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct wireless_dev *wdev = wil->wdev; - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system"); if (!netif_running(wil_to_ndev(wil))) { /* can always sleep when down */ @@ -59,7 +58,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) } out: - wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__, + wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n", is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc); return rc; @@ -70,8 +69,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); /* if netif up, hardware is alive, shut it down */ if (ndev->flags & IFF_UP) { @@ -86,7 +84,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) rc = wil->platform_ops.suspend(wil->platform_handle); out: - wil_dbg_pm(wil, "%s(%s) => %d\n", __func__, + wil_dbg_pm(wil, "suspend: %s => %d\n", is_runtime ? "runtime" : "system", rc); return rc; } @@ -96,8 +94,7 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); if (wil->platform_ops.resume) { rc = wil->platform_ops.resume(wil->platform_handle); @@ -115,7 +112,7 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime) rc = wil_up(wil); out: - wil_dbg_pm(wil, "%s(%s) => %d\n", __func__, + wil_dbg_pm(wil, "resume: %s => %d\n", is_runtime ? "runtime" : "system", rc); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index b9faae0278c9..3ff4f4ce9fef 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -60,7 +60,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, if (wil_is_pmc_allocated(pmc)) { /* sanity check */ - wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); + wil_err(wil, "ERROR pmc is already allocated\n"); goto no_release_err; } if ((num_descriptors <= 0) || (descriptor_size <= 0)) { @@ -90,21 +90,20 @@ void wil_pmc_alloc(struct wil6210_priv *wil, pmc->num_descriptors = num_descriptors; pmc->descriptor_size = descriptor_size; - wil_dbg_misc(wil, "%s: %d descriptors x %d bytes each\n", - __func__, num_descriptors, descriptor_size); + wil_dbg_misc(wil, "pmc_alloc: %d descriptors x %d bytes each\n", + num_descriptors, descriptor_size); /* allocate descriptors info list in pmc context*/ pmc->descriptors = kcalloc(num_descriptors, sizeof(struct desc_alloc_info), GFP_KERNEL); if (!pmc->descriptors) { - wil_err(wil, "%s: ERROR allocating pmc skb list\n", __func__); + wil_err(wil, "ERROR allocating pmc skb list\n"); goto no_release_err; } - wil_dbg_misc(wil, - "%s: allocated descriptors info list %p\n", - __func__, pmc->descriptors); + wil_dbg_misc(wil, "pmc_alloc: allocated descriptors info list %p\n", + pmc->descriptors); /* Allocate pring buffer and descriptors. * vring->va should be aligned on its size rounded up to power of 2 @@ -116,15 +115,14 @@ void wil_pmc_alloc(struct wil6210_priv *wil, GFP_KERNEL); wil_dbg_misc(wil, - "%s: allocated pring %p => %pad. %zd x %d = total %zd bytes\n", - __func__, + "pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n", pmc->pring_va, &pmc->pring_pa, sizeof(struct vring_tx_desc), num_descriptors, sizeof(struct vring_tx_desc) * num_descriptors); if (!pmc->pring_va) { - wil_err(wil, "%s: ERROR allocating pmc pring\n", __func__); + wil_err(wil, "ERROR allocating pmc pring\n"); goto release_pmc_skb_list; } @@ -143,9 +141,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, GFP_KERNEL); if (unlikely(!pmc->descriptors[i].va)) { - wil_err(wil, - "%s: ERROR allocating pmc descriptor %d", - __func__, i); + wil_err(wil, "ERROR allocating pmc descriptor %d", i); goto release_pmc_skbs; } @@ -165,21 +161,21 @@ void wil_pmc_alloc(struct wil6210_priv *wil, *_d = *d; } - wil_dbg_misc(wil, "%s: allocated successfully\n", __func__); + wil_dbg_misc(wil, "pmc_alloc: allocated successfully\n"); pmc_cmd.op = WMI_PMC_ALLOCATE; pmc_cmd.ring_size = cpu_to_le16(pmc->num_descriptors); pmc_cmd.mem_base = cpu_to_le64(pmc->pring_pa); - wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with ALLOCATE op\n", __func__); + wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n"); pmc->last_cmd_status = wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { wil_err(wil, - "%s: WMI_PMC_CMD with ALLOCATE op failed with status %d", - __func__, pmc->last_cmd_status); + "WMI_PMC_CMD with ALLOCATE op failed with status %d", + pmc->last_cmd_status); goto release_pmc_skbs; } @@ -188,7 +184,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, return; release_pmc_skbs: - wil_err(wil, "%s: exit on error: Releasing skbs...\n", __func__); + wil_err(wil, "exit on error: Releasing skbs...\n"); for (i = 0; pmc->descriptors[i].va && i < num_descriptors; i++) { dma_free_coherent(dev, descriptor_size, @@ -197,7 +193,7 @@ release_pmc_skbs: pmc->descriptors[i].va = NULL; } - wil_err(wil, "%s: exit on error: Releasing pring...\n", __func__); + wil_err(wil, "exit on error: Releasing pring...\n"); dma_free_coherent(dev, sizeof(struct vring_tx_desc) * num_descriptors, @@ -207,8 +203,7 @@ release_pmc_skbs: pmc->pring_va = NULL; release_pmc_skb_list: - wil_err(wil, "%s: exit on error: Releasing descriptors info list...\n", - __func__); + wil_err(wil, "exit on error: Releasing descriptors info list...\n"); kfree(pmc->descriptors); pmc->descriptors = NULL; @@ -232,24 +227,23 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) pmc->last_cmd_status = 0; if (!wil_is_pmc_allocated(pmc)) { - wil_dbg_misc(wil, "%s: Error, can't free - not allocated\n", - __func__); + wil_dbg_misc(wil, + "pmc_free: Error, can't free - not allocated\n"); pmc->last_cmd_status = -EPERM; mutex_unlock(&pmc->lock); return; } if (send_pmc_cmd) { - wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with RELEASE op\n", - __func__); + wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n"); pmc_cmd.op = WMI_PMC_RELEASE; pmc->last_cmd_status = wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { wil_err(wil, - "%s WMI_PMC_CMD with RELEASE op failed, status %d", - __func__, pmc->last_cmd_status); + "WMI_PMC_CMD with RELEASE op failed, status %d", + pmc->last_cmd_status); /* There's nothing we can do with this error. * Normally, it should never occur. * Continue to freeing all memory allocated for pmc. @@ -261,8 +255,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) size_t buf_size = sizeof(struct vring_tx_desc) * pmc->num_descriptors; - wil_dbg_misc(wil, "%s: free pring va %p\n", - __func__, pmc->pring_va); + wil_dbg_misc(wil, "pmc_free: free pring va %p\n", + pmc->pring_va); dma_free_coherent(dev, buf_size, pmc->pring_va, pmc->pring_pa); pmc->pring_va = NULL; @@ -281,11 +275,11 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) pmc->descriptors[i].pa); pmc->descriptors[i].va = NULL; } - wil_dbg_misc(wil, "%s: free descriptor info %d/%d\n", - __func__, i, pmc->num_descriptors); + wil_dbg_misc(wil, "pmc_free: free descriptor info %d/%d\n", i, + pmc->num_descriptors); wil_dbg_misc(wil, - "%s: free pmc descriptors info list %p\n", - __func__, pmc->descriptors); + "pmc_free: free pmc descriptors info list %p\n", + pmc->descriptors); kfree(pmc->descriptors); pmc->descriptors = NULL; } else { @@ -301,7 +295,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) */ int wil_pmc_last_cmd_status(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s: status %d\n", __func__, + wil_dbg_misc(wil, "pmc_last_cmd_status: status %d\n", wil->pmc.last_cmd_status); return wil->pmc.last_cmd_status; @@ -324,7 +318,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, mutex_lock(&pmc->lock); if (!wil_is_pmc_allocated(pmc)) { - wil_err(wil, "%s: error, pmc is not allocated!\n", __func__); + wil_err(wil, "error, pmc is not allocated!\n"); pmc->last_cmd_status = -EPERM; mutex_unlock(&pmc->lock); return -EPERM; @@ -333,8 +327,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, pmc_size = pmc->descriptor_size * pmc->num_descriptors; wil_dbg_misc(wil, - "%s: size %u, pos %lld\n", - __func__, (unsigned)count, *f_pos); + "pmc_read: size %u, pos %lld\n", + (u32)count, *f_pos); pmc->last_cmd_status = 0; @@ -343,15 +337,16 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, offset = *f_pos - (idx * pmc->descriptor_size); if (*f_pos >= pmc_size) { - wil_dbg_misc(wil, "%s: reached end of pmc buf: %lld >= %u\n", - __func__, *f_pos, (unsigned)pmc_size); + wil_dbg_misc(wil, + "pmc_read: reached end of pmc buf: %lld >= %u\n", + *f_pos, (u32)pmc_size); pmc->last_cmd_status = -ERANGE; goto out; } wil_dbg_misc(wil, - "%s: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n", - __func__, *f_pos, idx, offset, count); + "pmc_read: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n", + *f_pos, idx, offset, count); /* if no errors, return the copied byte count */ retval = simple_read_from_buffer(buf, diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 19ed127d4d05..7404b6f39c6a 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -349,8 +349,8 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status, agg_amsdu, agg_wsize, agg_timeout); if (rc || (status != WLAN_STATUS_SUCCESS)) { - wil_err(wil, "%s: do not apply ba, rc(%d), status(%d)\n", - __func__, rc, status); + wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, + status); goto out; } @@ -387,7 +387,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) txdata->addba_in_progress = true; rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout); if (rc) { - wil_err(wil, "%s: wmi_addba failed, rc (%d)", __func__, rc); + wil_err(wil, "wmi_addba failed, rc (%d)", rc); txdata->addba_in_progress = false; } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index c1b4bb03e997..072182e527e6 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,12 +29,12 @@ #include "trace.h" static bool rtap_include_phy_info; -module_param(rtap_include_phy_info, bool, S_IRUGO); +module_param(rtap_include_phy_info, bool, 0444); MODULE_PARM_DESC(rtap_include_phy_info, " Include PHY info in the radiotap header, default - no"); bool rx_align_2; -module_param(rx_align_2, bool, S_IRUGO); +module_param(rx_align_2, bool, 0444); MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); static inline uint wil_rx_snaplen(void) @@ -112,7 +112,7 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) size_t sz = vring->size * sizeof(vring->va[0]); uint i; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "vring_alloc:\n"); BUILD_BUG_ON(sizeof(vring->va[0]) != 32); @@ -745,7 +745,7 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); return; } - wil_dbg_txrx(wil, "%s()\n", __func__); + wil_dbg_txrx(wil, "rx_handle\n"); while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { (*quota)--; @@ -768,7 +768,7 @@ int wil_rx_init(struct wil6210_priv *wil, u16 size) struct vring *vring = &wil->vring_rx; int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "rx_init\n"); if (vring->va) { wil_err(wil, "Rx ring already allocated\n"); @@ -799,7 +799,7 @@ void wil_rx_fini(struct wil6210_priv *wil) { struct vring *vring = &wil->vring_rx; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "rx_fini\n"); if (vring->va) wil_vring_free(wil, vring, 0); @@ -851,7 +851,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; - wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__, + wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); lockdep_assert_held(&wil->mutex); @@ -931,7 +931,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; - wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__, + wil_dbg_misc(wil, "vring_init_bcast: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); lockdep_assert_held(&wil->mutex); @@ -993,7 +993,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) if (!vring->va) return; - wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); + wil_dbg_misc(wil, "vring_fini_tx: id=%d\n", id); spin_lock_bh(&txdata->lock); txdata->dot1x_open = false; @@ -1032,12 +1032,14 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, struct vring *v = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; - wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", - __func__, eth->h_dest, i); + wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", + eth->h_dest, i); if (v->va && txdata->enabled) { return v; } else { - wil_dbg_txrx(wil, "vring[%d] not valid\n", i); + wil_dbg_txrx(wil, + "find_tx_ucast: vring[%d] not valid\n", + i); return NULL; } } @@ -1193,17 +1195,6 @@ found: return v; } -static struct vring *wil_find_tx_bcast(struct wil6210_priv *wil, - struct sk_buff *skb) -{ - struct wireless_dev *wdev = wil->wdev; - - if (wdev->iftype != NL80211_IFTYPE_AP) - return wil_find_tx_bcast_2(wil, skb); - - return wil_find_tx_bcast_1(wil, skb); -} - static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, int vring_index) { @@ -1373,8 +1364,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, int gso_type; int rc = -EINVAL; - wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", - __func__, skb->len, vring_index); + wil_dbg_txrx(wil, "tx_vring_tso: %d bytes to vring %d\n", skb->len, + vring_index); if (unlikely(!txdata->enabled)) return -EINVAL; @@ -1643,8 +1634,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, bool mcast = (vring_index == wil->bcast_vring); uint len = skb_headlen(skb); - wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", - __func__, skb->len, vring_index); + wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, + vring_index); if (unlikely(!txdata->enabled)) return -EINVAL; @@ -1884,7 +1875,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) static bool pr_once_fw; int rc; - wil_dbg_txrx(wil, "%s()\n", __func__); + wil_dbg_txrx(wil, "start_xmit\n"); if (unlikely(!test_bit(wil_status_fwready, wil->status))) { if (!pr_once_fw) { wil_err(wil, "FW not ready\n"); @@ -1903,12 +1894,26 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) pr_once_fw = false; /* find vring */ - if (wil->wdev->iftype == NL80211_IFTYPE_STATION) { - /* in STA mode (ESS), all to same VRING */ + if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) { + /* in STA mode (ESS), all to same VRING (to AP) */ vring = wil_find_tx_vring_sta(wil, skb); - } else { /* direct communication, find matching VRING */ - vring = bcast ? wil_find_tx_bcast(wil, skb) : - wil_find_tx_ucast(wil, skb); + } else if (bcast) { + if (wil->pbss) + /* in pbss, no bcast VRING - duplicate skb in + * all stations VRINGs + */ + vring = wil_find_tx_bcast_2(wil, skb); + else if (wil->wdev->iftype == NL80211_IFTYPE_AP) + /* AP has a dedicated bcast VRING */ + vring = wil_find_tx_bcast_1(wil, skb); + else + /* unexpected combination, fallback to duplicating + * the skb in all stations VRINGs + */ + vring = wil_find_tx_bcast_2(wil, skb); + } else { + /* unicast, find specific VRING by dest. address */ + vring = wil_find_tx_ucast(wil, skb); } if (unlikely(!vring)) { wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); @@ -1982,7 +1987,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) return 0; } - wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); + wil_dbg_txrx(wil, "tx_complete: (%d)\n", ringid); used_before_complete = wil_vring_used_tx(vring); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 237e1666df2d..085a2dbfa21d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -33,10 +33,12 @@ extern int agg_wsize; extern u32 vring_idle_trsh; extern bool rx_align_2; extern bool debug_fw; +extern bool disable_ap_sme; #define WIL_NAME "wil6210" -#define WIL_FW_NAME "wil6210.fw" /* code */ -#define WIL_FW2_NAME "wil6210.brd" /* board & radio parameters */ +#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */ +#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */ +#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */ #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ @@ -98,6 +100,9 @@ static inline u32 wil_mtu2macbuf(u32 mtu) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \ (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) +#define WIL_MAX_DMG_AID 254 /* for DMG only 1-254 allowed (see + * 802.11REVmc/D5.0, section 9.4.1.8) + */ /* Hardware definitions begin */ /* @@ -249,7 +254,12 @@ struct RGF_ICR { #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ - #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) + #define JTAG_DEV_ID_SPARROW (0x2632072f) + +#define RGF_USER_REVISION_ID (0x88afe4) +#define RGF_USER_REVISION_ID_MASK (3) + #define REVISION_ID_SPARROW_B0 (0x0) + #define REVISION_ID_SPARROW_D0 (0x3) /* crash codes for FW/Ucode stored here */ #define RGF_FW_ASSERT_CODE (0x91f020) @@ -257,7 +267,8 @@ struct RGF_ICR { enum { HW_VER_UNKNOWN, - HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ + HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */ + HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */ }; /* popular locations */ @@ -512,6 +523,7 @@ struct wil_sta_info { unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)]; struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM]; struct wil_tid_crypto_rx group_crypto_rx; + u8 aid; /* 1-254; 0 if unknown/not reported */ }; enum { @@ -583,7 +595,9 @@ struct wil6210_priv { DECLARE_BITMAP(status, wil_status_last); u8 fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; + u8 chip_revision; const char *hw_name; + const char *wil_fw_name; DECLARE_BITMAP(hw_capabilities, hw_capability_last); DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); u8 n_mids; /* number of additional MIDs as reported by FW */ @@ -653,6 +667,7 @@ struct wil6210_priv { struct dentry *debug; struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; u8 discovery_mode; + u8 abft_len; void *platform_handle; struct wil_platform_ops platform_ops; @@ -816,8 +831,8 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect); +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta); int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); @@ -827,6 +842,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile); int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid); int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); @@ -918,6 +934,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type); int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd); int wil_request_firmware(struct wil6210_priv *wil, const char *name, bool load); +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime); diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index d051eea47a54..e53cf0cf7031 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Qualcomm Atheros, Inc. + * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -62,13 +62,13 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) u32 host_min, dump_size, offset, len; if (wil_fw_get_crash_dump_bounds(wil, &dump_size, &host_min)) { - wil_err(wil, "%s: fail to obtain crash dump size\n", __func__); + wil_err(wil, "fail to obtain crash dump size\n"); return -EINVAL; } if (dump_size > size) { - wil_err(wil, "%s: not enough space for dump. Need %d have %d\n", - __func__, dump_size, size); + wil_err(wil, "not enough space for dump. Need %d have %d\n", + dump_size, size); return -EINVAL; } @@ -83,8 +83,9 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) len = map->to - map->from; offset = map->host - host_min; - wil_dbg_misc(wil, "%s() - dump %s, size %d, offset %d\n", - __func__, fw_mapping[i].name, len, offset); + wil_dbg_misc(wil, + "fw_copy_crash_dump: - dump %s, size %d, offset %d\n", + fw_mapping[i].name, len, offset); wil_memcpy_fromio_32((void * __force)(dest + offset), (const void __iomem * __force)data, len); @@ -99,7 +100,7 @@ void wil_fw_core_dump(struct wil6210_priv *wil) u32 fw_dump_size; if (wil_fw_get_crash_dump_bounds(wil, &fw_dump_size, NULL)) { - wil_err(wil, "%s: fail to get fw dump size\n", __func__); + wil_err(wil, "fail to get fw dump size\n"); return; } @@ -115,6 +116,5 @@ void wil_fw_core_dump(struct wil6210_priv *wil) * after 5 min */ dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size, GFP_KERNEL); - wil_info(wil, "%s: fw core dumped, size %d bytes\n", __func__, - fw_dump_size); + wil_info(wil, "fw core dumped, size %d bytes\n", fw_dump_size); } diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 7585003bef67..1f22c19696b1 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,16 +24,16 @@ #include "trace.h" static uint max_assoc_sta = WIL6210_MAX_CID; -module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR); +module_param(max_assoc_sta, uint, 0644); MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); int agg_wsize; /* = 0; */ -module_param(agg_wsize, int, S_IRUGO | S_IWUSR); +module_param(agg_wsize, int, 0644); MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;" " 0 - use default; < 0 - don't auto-establish"); u8 led_id = WIL_LED_INVALID_ID; -module_param(led_id, byte, S_IRUGO); +module_param(led_id, byte, 0444); MODULE_PARM_DESC(led_id, " 60G device led enablement. Set the led ID (0-2) to enable"); @@ -495,8 +495,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } ch = evt->channel + 1; - wil_info(wil, "Connect %pM channel [%d] cid %d\n", - evt->bssid, ch, evt->cid); + wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n", + evt->bssid, ch, evt->cid, evt->aid); wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, evt->assoc_info, len - sizeof(*evt), true); @@ -539,8 +539,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (wil->sta[evt->cid].status != wil_sta_unused) { - wil_err(wil, "%s: AP: Invalid status %d for CID %d\n", - __func__, wil->sta[evt->cid].status, evt->cid); + wil_err(wil, "AP: Invalid status %d for CID %d\n", + wil->sta[evt->cid].status, evt->cid); mutex_unlock(&wil->mutex); return; } @@ -553,22 +553,19 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) rc = wil_tx_init(wil, evt->cid); if (rc) { - wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", - __func__, evt->cid, rc); + wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n", + evt->cid, rc); wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, - WLAN_REASON_UNSPECIFIED, false); + WLAN_REASON_UNSPECIFIED, false, false); } else { - wil_info(wil, "%s: successful connection to CID %d\n", - __func__, evt->cid); + wil_info(wil, "successful connection to CID %d\n", evt->cid); } if ((wdev->iftype == NL80211_IFTYPE_STATION) || (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { if (rc) { netif_carrier_off(ndev); - wil_err(wil, - "%s: cfg80211_connect_result with failure\n", - __func__); + wil_err(wil, "cfg80211_connect_result with failure\n"); cfg80211_connect_result(ndev, evt->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, @@ -583,8 +580,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { - if (rc) + if (rc) { + if (disable_ap_sme) + /* notify new_sta has failed */ + cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL); goto out; + } memset(&sinfo, 0, sizeof(sinfo)); @@ -597,12 +598,13 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); } else { - wil_err(wil, "%s: unhandled iftype %d for CID %d\n", - __func__, wdev->iftype, evt->cid); + wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype, + evt->cid); goto out; } wil->sta[evt->cid].status = wil_sta_connected; + wil->sta[evt->cid].aid = evt->aid; set_bit(wil_status_fwconnected, wil->status); wil_update_net_queues_bh(wil, NULL, false); @@ -687,6 +689,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) { struct wmi_vring_en_event *evt = d; u8 vri = evt->vring_index; + struct wireless_dev *wdev = wil_to_wdev(wil); wil_dbg_wmi(wil, "Enable vring %d\n", vri); @@ -694,7 +697,12 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) wil_err(wil, "Enable for invalid vring %d\n", vri); return; } - wil->vring_tx_data[vri].dot1x_open = true; + + if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme) + /* in AP mode with disable_ap_sme, this is done by + * wil_cfg80211_change_station() + */ + wil->vring_tx_data[vri].dot1x_open = true; if (vri == wil->bcast_vring) /* no BA for bcast */ return; if (agg_wsize >= 0) @@ -919,8 +927,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil) offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); if (immed_reply) { - wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", - __func__, wil->reply_id); + wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n", + wil->reply_id); kfree(evt); num_immed_reply++; complete(&wil->wmi_call); @@ -934,7 +942,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) } } /* normally, 1 event per IRQ should be processed */ - wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__, + wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n", n - num_immed_reply, num_immed_reply); } @@ -950,6 +958,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, wil->reply_id = reply_id; wil->reply_buf = reply; wil->reply_size = reply_size; + reinit_completion(&wil->wmi_call); spin_unlock(&wil->wmi_ev_lock); rc = __wmi_send(wil, cmdid, buf, len); @@ -1069,6 +1078,8 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, .is_go = is_go, + .disable_ap_sme = disable_ap_sme, + .abft_len = wil->abft_len, }; struct { struct wmi_cmd_hdr wmi; @@ -1086,6 +1097,13 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, cmd.pcp_max_assoc_sta = WIL6210_MAX_CID; } + if (disable_ap_sme && + !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME, + wil->fw_capabilities)) { + wil_err(wil, "disable_ap_sme not supported by FW\n"); + return -EOPNOTSUPP; + } + /* * Processing time may be huge, in case of secure AP it takes about * 3500ms for FW to start AP @@ -1352,7 +1370,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) struct wmi_listen_started_event evt; } __packed reply; - wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off"); + wil_info(wil, "(%s)\n", on ? "on" : "off"); if (on) { rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, @@ -1456,12 +1474,15 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect) +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta) { int rc; u16 reason_code; - struct wmi_disconnect_sta_cmd cmd = { + struct wmi_disconnect_sta_cmd disc_sta_cmd = { + .disconnect_reason = cpu_to_le16(reason), + }; + struct wmi_del_sta_cmd del_sta_cmd = { .disconnect_reason = cpu_to_le16(reason), }; struct { @@ -1469,12 +1490,19 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, struct wmi_disconnect_event evt; } __packed reply; - ether_addr_copy(cmd.dst_mac, mac); - - wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason); + wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); - rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd), - WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000); + if (del_sta) { + ether_addr_copy(del_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd, + sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } else { + ether_addr_copy(disc_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd, + sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } /* failure to disconnect in reasonable time treated as FW error */ if (rc) { wil_fw_error_recovery(wil); @@ -1507,8 +1535,8 @@ int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) .amsdu = 0, }; - wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__, - ringid, size, timeout); + wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size, + timeout); return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd)); } @@ -1520,8 +1548,7 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) .reason = cpu_to_le16(reason), }; - wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__, - ringid, reason); + wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason); return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd)); } @@ -1533,8 +1560,8 @@ int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) .reason = cpu_to_le16(reason), }; - wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__, - cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason); + wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, + (cidxtid >> 4) & 0xf, reason); return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd)); } @@ -1686,11 +1713,29 @@ int wmi_abort_scan(struct wil6210_priv *wil) return rc; } +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) +{ + int rc; + struct wmi_new_sta_cmd cmd = { + .aid = aid, + }; + + wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid); + + ether_addr_copy(cmd.dst_mac, mac); + + rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd)); + if (rc) + wil_err(wil, "Failed to send new sta (%d)\n", rc); + + return rc; +} + void wmi_event_flush(struct wil6210_priv *wil) { struct pending_wmi_event *evt, *t; - wil_dbg_wmi(wil, "%s()\n", __func__); + wil_dbg_wmi(wil, "event_flush\n"); list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { list_del(&evt->list); @@ -1731,8 +1776,8 @@ static void wmi_event_handle(struct wil6210_priv *wil, WARN_ON(wil->reply_buf); wmi_evt_call_handler(wil, id, evt_data, len - sizeof(*wmi)); - wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", - __func__, id); + wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n", + id); complete(&wil->wmi_call); return; } @@ -1779,11 +1824,11 @@ void wmi_event_worker(struct work_struct *work) struct pending_wmi_event *evt; struct list_head *lh; - wil_dbg_wmi(wil, "Start %s\n", __func__); + wil_dbg_wmi(wil, "event_worker: Start\n"); while ((lh = next_wmi_ev(wil)) != NULL) { evt = list_entry(lh, struct pending_wmi_event, list); wmi_event_handle(wil, &evt->event.hdr); kfree(evt); } - wil_dbg_wmi(wil, "Finished %s\n", __func__); + wil_dbg_wmi(wil, "event_worker: Finished\n"); } diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index d93a4d490d24..7c9fee57aa91 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * * Permission to use, copy, modify, and/or distribute this software for any @@ -56,6 +56,8 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PS_CONFIG = 1, WMI_FW_CAPABILITY_RF_SECTORS = 2, WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, + WMI_FW_CAPABILITY_DISABLE_AP_SME = 4, + WMI_FW_CAPABILITY_WMI_ONLY = 5, WMI_FW_CAPABILITY_MAX, }; @@ -185,8 +187,11 @@ enum wmi_command_id { WMI_RS_CFG_CMDID = 0x921, WMI_GET_DETAILED_RS_RES_CMDID = 0x922, WMI_AOA_MEAS_CMDID = 0x923, + WMI_BRP_SET_ANT_LIMIT_CMDID = 0x924, WMI_SET_MGMT_RETRY_LIMIT_CMDID = 0x930, WMI_GET_MGMT_RETRY_LIMIT_CMDID = 0x931, + WMI_NEW_STA_CMDID = 0x935, + WMI_DEL_STA_CMDID = 0x936, WMI_TOF_SESSION_START_CMDID = 0x991, WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, WMI_TOF_SET_LCR_CMDID = 0x993, @@ -543,7 +548,10 @@ struct wmi_pcp_start_cmd { u8 pcp_max_assoc_sta; u8 hidden_ssid; u8 is_go; - u8 reserved0[7]; + u8 reserved0[5]; + /* abft_len override if non-0 */ + u8 abft_len; + u8 disable_ap_sme; u8 network_type; u8 channel; u8 disable_sec_offload; @@ -902,6 +910,18 @@ struct wmi_set_mgmt_retry_limit_cmd { u8 reserved[3]; } __packed; +/* WMI_NEW_STA_CMDID */ +struct wmi_new_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + u8 aid; +} __packed; + +/* WMI_DEL_STA_CMDID */ +struct wmi_del_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 disconnect_reason; +} __packed; + enum wmi_tof_burst_duration { WMI_TOF_BURST_DURATION_250_USEC = 2, WMI_TOF_BURST_DURATION_500_USEC = 3, @@ -1067,6 +1087,7 @@ enum wmi_event_id { WMI_RS_CFG_DONE_EVENTID = 0x1921, WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922, WMI_AOA_MEAS_EVENTID = 0x1923, + WMI_BRP_SET_ANT_LIMIT_EVENTID = 0x1924, WMI_SET_MGMT_RETRY_LIMIT_EVENTID = 0x1930, WMI_GET_MGMT_RETRY_LIMIT_EVENTID = 0x1931, WMI_TOF_SESSION_END_EVENTID = 0x1991, @@ -1287,12 +1308,13 @@ struct wmi_connect_event { u8 assoc_req_len; u8 assoc_resp_len; u8 cid; - u8 reserved2[3]; + u8 aid; + u8 reserved2[2]; /* not in use */ u8 assoc_info[0]; } __packed; -/* WMI_DISCONNECT_EVENTID */ +/* disconnect_reason */ enum wmi_disconnect_reason { WMI_DIS_REASON_NO_NETWORK_AVAIL = 0x01, /* bmiss */ @@ -1310,6 +1332,7 @@ enum wmi_disconnect_reason { WMI_DIS_REASON_IBSS_MERGE = 0x0E, }; +/* WMI_DISCONNECT_EVENTID */ struct wmi_disconnect_event { /* reason code, see 802.11 spec. */ __le16 protocol_reason_status; @@ -1759,6 +1782,42 @@ struct wmi_get_detailed_rs_res_event { u8 reserved[3]; } __packed; +/* BRP antenna limit mode */ +enum wmi_brp_ant_limit_mode { + /* Disable BRP force antenna limit */ + WMI_BRP_ANT_LIMIT_MODE_DISABLE = 0x00, + /* Define maximal antennas limit. Only effective antennas will be + * actually used + */ + WMI_BRP_ANT_LIMIT_MODE_EFFECTIVE = 0x01, + /* Force a specific number of antennas */ + WMI_BRP_ANT_LIMIT_MODE_FORCE = 0x02, + /* number of BRP antenna limit modes */ + WMI_BRP_ANT_LIMIT_MODES_NUM = 0x03, +}; + +/* WMI_BRP_SET_ANT_LIMIT_CMDID */ +struct wmi_brp_set_ant_limit_cmd { + /* connection id */ + u8 cid; + /* enum wmi_brp_ant_limit_mode */ + u8 limit_mode; + /* antenna limit count, 1-27 + * disable_mode - ignored + * effective_mode - upper limit to number of antennas to be used + * force_mode - exact number of antennas to be used + */ + u8 ant_limit; + u8 reserved; +} __packed; + +/* WMI_BRP_SET_ANT_LIMIT_EVENTID */ +struct wmi_brp_set_ant_limit_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + /* broadcast connection ID */ #define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST (0xFFFFFFFF) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 72139b579b18..5bc2ba214735 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -1104,6 +1104,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356), { /* end: all zeroes */ } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index e21f7600122b..76693df34742 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -218,9 +218,6 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) * interface functions from common layer */ -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_event); /* Receive async event packet from firmware. Callee disposes of rxp. */ @@ -241,13 +238,12 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); /* Configure the "global" bus state used by upper layers */ void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state); -int brcmf_bus_start(struct device *dev); +int brcmf_bus_started(struct device *dev); s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); void brcmf_bus_add_txhdrlen(struct device *dev, uint len); #ifdef CONFIG_BRCMFMAC_SDIO void brcmf_sdio_exit(void); -void brcmf_sdio_init(void); void brcmf_sdio_register(void); #endif #ifdef CONFIG_BRCMFMAC_USB diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 15eaf722b54b..0e28d0710af5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -138,7 +138,6 @@ static struct ieee80211_rate __wl_rates[] = { .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ - .flags = IEEE80211_CHAN_DISABLED, \ .max_antenna_gain = 0, \ .max_power = 30, \ } @@ -147,7 +146,6 @@ static struct ieee80211_rate __wl_rates[] = { .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ - .flags = IEEE80211_CHAN_DISABLED, \ .max_antenna_gain = 0, \ .max_power = 30, \ } @@ -328,7 +326,7 @@ u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, * triples, returning a pointer to the substring whose first element * matches tag */ -const struct brcmf_tlv * +static const struct brcmf_tlv * brcmf_parse_tlvs(const void *buf, int buflen, uint key) { const struct brcmf_tlv *elt = buf; @@ -3332,7 +3330,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, goto out_err; } - data += sizeof(struct brcmf_pno_scanresults_le); netinfo_start = brcmf_get_netinfo_array(pfn_result); for (i = 0; i < result_count; i++) { @@ -3480,8 +3477,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, return -EINVAL; } - data += sizeof(struct brcmf_pno_scanresults_le); - netinfo = (struct brcmf_pno_net_info_le *)data; + netinfo = brcmf_get_netinfo_array(pfn_result); memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len); cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len; cfg->wowl.nd->n_channels = 1; @@ -5071,6 +5067,29 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, return ret; } +static int +brcmf_cfg80211_update_conn_params(struct wiphy *wiphy, + struct net_device *ndev, + struct cfg80211_connect_params *sme, + u32 changed) +{ + struct brcmf_if *ifp; + int err; + + if (!(changed & UPDATE_ASSOC_IES)) + return 0; + + ifp = netdev_priv(ndev); + err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, + sme->ie, sme->ie_len); + if (err) + brcmf_err("Set Assoc REQ IE Failed\n"); + else + brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); + + return err; +} + #ifdef CONFIG_PM static int brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev, @@ -5138,6 +5157,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = { .crit_proto_start = brcmf_cfg80211_crit_proto_start, .crit_proto_stop = brcmf_cfg80211_crit_proto_stop, .tdls_oper = brcmf_cfg80211_tdls_oper, + .update_connect_params = brcmf_cfg80211_update_conn_params, }; struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, @@ -5825,7 +5845,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, u32 i, j; u32 total; u32 chaninfo; - u32 index; pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); @@ -5873,33 +5892,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, ch.bw == BRCMU_CHAN_BW_80) continue; - channel = band->channels; - index = band->n_channels; + channel = NULL; for (j = 0; j < band->n_channels; j++) { - if (channel[j].hw_value == ch.control_ch_num) { - index = j; + if (band->channels[j].hw_value == ch.control_ch_num) { + channel = &band->channels[j]; break; } } - channel[index].center_freq = - ieee80211_channel_to_frequency(ch.control_ch_num, - band->band); - channel[index].hw_value = ch.control_ch_num; + if (!channel) { + /* It seems firmware supports some channel we never + * considered. Something new in IEEE standard? + */ + brcmf_err("Ignoring unexpected firmware channel %d\n", + ch.control_ch_num); + continue; + } /* assuming the chanspecs order is HT20, * HT40 upper, HT40 lower, and VHT80. */ if (ch.bw == BRCMU_CHAN_BW_80) { - channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ; + channel->flags &= ~IEEE80211_CHAN_NO_80MHZ; } else if (ch.bw == BRCMU_CHAN_BW_40) { - brcmf_update_bw40_channel_flag(&channel[index], &ch); + brcmf_update_bw40_channel_flag(channel, &ch); } else { /* enable the channel and disable other bandwidths * for now as mentioned order assure they are enabled * for subsequent chanspecs. */ - channel[index].flags = IEEE80211_CHAN_NO_HT40 | - IEEE80211_CHAN_NO_80MHZ; + channel->flags = IEEE80211_CHAN_NO_HT40 | + IEEE80211_CHAN_NO_80MHZ; ch.bw = BRCMU_CHAN_BW_20; cfg->d11inf.encchspec(&ch); chaninfo = ch.chspec; @@ -5907,11 +5929,11 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, &chaninfo); if (!err) { if (chaninfo & WL_CHAN_RADAR) - channel[index].flags |= + channel->flags |= (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR); if (chaninfo & WL_CHAN_PASSIVE) - channel[index].flags |= + channel->flags |= IEEE80211_CHAN_NO_IR; } } @@ -6341,7 +6363,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) } #ifdef CONFIG_PM -static struct wiphy_wowlan_support brcmf_wowlan_support = { +static const struct wiphy_wowlan_support brcmf_wowlan_support = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, .n_patterns = BRCMF_WOWL_MAXPATTERNS, .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE, @@ -6354,19 +6376,29 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) { #ifdef CONFIG_PM struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct wiphy_wowlan_support *wowl; + + wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support), + GFP_KERNEL); + if (!wowl) { + brcmf_err("only support basic wowlan features\n"); + wiphy->wowlan = &brcmf_wowlan_support; + return; + } if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) { if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) { - brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; + wowl->flags |= WIPHY_WOWLAN_NET_DETECT; + wowl->max_nd_match_sets = BRCMF_PNO_MAX_PFN_COUNT; init_waitqueue_head(&cfg->wowl.nd_data_wait); } } if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) { - brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY; - brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE; + wowl->flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY; + wowl->flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE; } - wiphy->wowlan = &brcmf_wowlan_support; + wiphy->wowlan = wowl; #endif } @@ -6477,8 +6509,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->bands[NL80211_BAND_5GHZ] = band; } } - err = brcmf_setup_wiphybands(wiphy); - return err; + return 0; } static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) @@ -6748,6 +6779,10 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels); kfree(wiphy->bands[NL80211_BAND_5GHZ]); } +#if IS_ENABLED(CONFIG_PM) + if (wiphy->wowlan != &brcmf_wowlan_support) + kfree(wiphy->wowlan); +#endif wiphy_free(wiphy); } @@ -6843,6 +6878,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, goto priv_out; } + err = brcmf_setup_wiphybands(wiphy); + if (err) { + brcmf_err("Setting wiphy bands failed (%d)\n", err); + goto wiphy_unreg_out; + } + /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), * setup 40MHz in 2GHz band and enable OBSS scanning. */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 0c9a7081fca9..8f19d95d4175 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -396,8 +396,6 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len); s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); -const struct brcmf_tlv * -brcmf_parse_tlvs(const void *buf, int buflen, uint key); u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, struct ieee80211_channel *ch); bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 3e15d64c6481..f7c8c2e80349 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -74,7 +74,7 @@ module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); #ifdef DEBUG -/* always succeed brcmf_bus_start() */ +/* always succeed brcmf_bus_started() */ static int brcmf_ignore_probe_fail; module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0); MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); @@ -299,11 +299,9 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, } } } - if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) { - /* No platform data for this device. In case of SDIO try OF - * (Open Firwmare) Device Tree. - */ - brcmf_of_probe(dev, &settings->bus.sdio); + if (!found) { + /* No platform data for this device, try OF (Open Firwmare) */ + brcmf_of_probe(dev, bus_type, settings); } return settings; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index bd095abca393..a62f8e70b320 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -65,6 +65,8 @@ struct brcmf_mp_device { } bus; }; +void brcmf_c_set_joinpref_default(struct brcmf_if *ifp); + struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, enum brcmf_bus_type bus_type, u32 chip, u32 chiprev); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9e6f60a0ec3e..b73a55b00fa7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -966,7 +966,7 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data) return 0; } -int brcmf_bus_start(struct device *dev) +int brcmf_bus_started(struct device *dev) { int ret = -1; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -1075,16 +1075,6 @@ void brcmf_bus_add_txhdrlen(struct device *dev, uint len) } } -static void brcmf_bus_detach(struct brcmf_pub *drvr) -{ - brcmf_dbg(TRACE, "Enter\n"); - - if (drvr) { - /* Stop the bus module */ - brcmf_bus_stop(drvr->bus_if); - } -} - void brcmf_dev_reset(struct device *dev) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -1131,7 +1121,7 @@ void brcmf_detach(struct device *dev) brcmf_fws_deinit(drvr); - brcmf_bus_detach(drvr); + brcmf_bus_stop(drvr->bus_if); brcmf_proto_detach(drvr); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index c94dcab260d0..de3197be5491 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -216,7 +216,6 @@ 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/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index 425c41dc0a59..aee6e5937c41 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -23,14 +23,17 @@ #include "common.h" #include "of.h" -void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio) +void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) { + struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; struct device_node *np = dev->of_node; int irq; u32 irqf; u32 val; - if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) + if (!np || bus_type != BRCMF_BUSTYPE_SDIO || + !of_device_is_compatible(np, "brcm,bcm4329-fmac")) return; if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h index a9d94c15d0f5..95b7032d54b1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h @@ -14,9 +14,11 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef CONFIG_OF -void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio); +void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings); #else -static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio) +static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) { } #endif /* CONFIG_OF */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 048027f2085b..6fae4cf3f6ab 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -601,7 +601,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo) { u32 config; - brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); /* BAR1 window may not be sized properly */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0); @@ -1572,7 +1571,7 @@ static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo) if (ret) { brcmf_err("brcmf_attach failed\n"); } else { - ret = brcmf_bus_start(&devinfo->pdev->dev); + ret = brcmf_bus_started(&devinfo->pdev->dev); if (ret) brcmf_err("dongle is not responding\n"); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index dfb0658713d9..c5744b45ec8f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1661,7 +1661,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) pfirst->len, pfirst->next, pfirst->prev); skb_unlink(pfirst, &bus->glom); - if (brcmf_sdio_fromevntchan(pfirst->data)) + if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN])) brcmf_rx_event(bus->sdiodev->dev, pfirst); else brcmf_rx_frame(bus->sdiodev->dev, pfirst, @@ -4065,7 +4065,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, sdio_release_host(sdiodev->func[1]); - err = brcmf_bus_start(dev); + err = brcmf_bus_started(dev); if (err != 0) { brcmf_err("dongle is not responding\n"); goto fail; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 2f978a39b58a..d93ebbdc7737 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -1148,7 +1148,7 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) if (ret) goto fail; - ret = brcmf_bus_start(devinfo->dev); + ret = brcmf_bus_started(devinfo->dev); if (ret) goto fail; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index affe760c8c22..376c79337a0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -2310,7 +2310,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, { struct iwl_priv *priv = file->private_data; bool restart_fw = iwlwifi_mod_params.restart_fw; - int ret; + int __maybe_unused ret; iwlwifi_mod_params.restart_fw = true; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 8c0719468d00..2a04d0cd71ae 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -163,7 +163,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, REGULATORY_DISABLE_BEACON_HINTS; #ifdef CONFIG_PM_SLEEP - if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && + if (priv->fw->img[IWL_UCODE_WOWLAN].num_sec && priv->trans->ops->d3_suspend && priv->trans->ops->d3_resume && device_can_wakeup(priv->trans->dev)) { diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index b95c2d76db33..710dbbefd551 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -364,7 +364,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv, /* get the traffic load value for tid */ -static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) +static void rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; @@ -372,14 +372,14 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) struct iwl_traffic_load *tl = NULL; if (tid >= IWL_MAX_TID_COUNT) - return 0; + return; tl = &(lq_data->load[tid]); curr_time -= curr_time % TID_ROUND_VALUE; if (!(tl->queue_count)) - return 0; + return; time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); index = time_diff / TID_QUEUE_CELL_SPACING; @@ -388,8 +388,6 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) /* TID_MAX_TIME_DIFF */ if (index >= TID_QUEUE_MAX_SIZE) rs_tl_rm_old_stats(tl, curr_time); - - return tl->total; } static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, @@ -397,7 +395,6 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct ieee80211_sta *sta) { int ret = -EAGAIN; - u32 load; /* * Don't create TX aggregation sessions when in high @@ -410,7 +407,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, return ret; } - load = rs_tl_get_load(lq_data, tid); + rs_tl_get_load(lq_data, tid); IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c index c7509c51e9d9..d6013bfe991c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c @@ -407,7 +407,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); /* No init ucode required? Curious, but maybe ok */ - if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len) + if (!priv->fw->img[IWL_UCODE_INIT].num_sec) return 0; iwl_init_notification_wait(&priv->notif_wait, &calib_wait, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c index 0b9f6a7bc834..39335b7b0c16 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-6000.c @@ -371,4 +371,4 @@ const struct iwl_cfg iwl6000_3agn_cfg = { MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index d4b73dedf89b..a72e58623d3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -73,8 +73,8 @@ /* Highest firmware API version supported */ #define IWL7260_UCODE_API_MAX 17 #define IWL7265_UCODE_API_MAX 17 -#define IWL7265D_UCODE_API_MAX 26 -#define IWL3168_UCODE_API_MAX 26 +#define IWL7265D_UCODE_API_MAX 28 +#define IWL3168_UCODE_API_MAX 28 /* Lowest firmware API version supported */ #define IWL7260_UCODE_API_MIN 17 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index d02ca1491d16..df0fc24e99e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -70,8 +70,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL8000_UCODE_API_MAX 26 -#define IWL8265_UCODE_API_MAX 26 +#define IWL8000_UCODE_API_MAX 28 +#define IWL8265_UCODE_API_MAX 28 /* Lowest firmware API version supported */ #define IWL8000_UCODE_API_MIN 17 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index ff850410d897..a5f0c0bf85ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -55,7 +55,7 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 26 +#define IWL9000_UCODE_API_MAX 28 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 17 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c b/drivers/net/wireless/intel/iwlwifi/iwl-a000.c index ea1618525878..82f18d967c40 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-a000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-a000.c @@ -55,7 +55,7 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL_A000_UCODE_API_MAX 26 +#define IWL_A000_UCODE_API_MAX 28 /* Lowest firmware API version supported */ #define IWL_A000_UCODE_API_MIN 24 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 45b2f679e4d8..d22821501676 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -166,8 +166,9 @@ static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) { int i; - for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) + for (i = 0; i < img->num_sec; i++) iwl_free_fw_desc(drv, &img->sec[i]); + kfree(img->sec); } static void iwl_dealloc_ucode(struct iwl_drv *drv) @@ -179,8 +180,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) kfree(drv->fw.dbg_conf_tlv[i]); for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) kfree(drv->fw.dbg_trigger_tlv[i]); - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++) - kfree(drv->fw.dbg_mem_tlv[i]); + kfree(drv->fw.dbg_mem_tlv); for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) iwl_free_fw_img(drv, drv->fw.img + i); @@ -241,7 +241,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) } struct fw_img_parsing { - struct fw_sec sec[IWL_UCODE_SECTION_MAX]; + struct fw_sec *sec; int sec_counter; }; @@ -276,7 +276,8 @@ struct iwl_firmware_pieces { size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; - struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX]; + struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv; + size_t n_dbg_mem_tlv; }; /* @@ -290,11 +291,33 @@ static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces, return &pieces->img[type].sec[sec]; } +static void alloc_sec_data(struct iwl_firmware_pieces *pieces, + enum iwl_ucode_type type, + int sec) +{ + struct fw_img_parsing *img = &pieces->img[type]; + struct fw_sec *sec_memory; + int size = sec + 1; + size_t alloc_size = sizeof(*img->sec) * size; + + if (img->sec && img->sec_counter >= size) + return; + + sec_memory = krealloc(img->sec, alloc_size, GFP_KERNEL); + if (!sec_memory) + return; + + img->sec = sec_memory; + img->sec_counter = size; +} + static void set_sec_data(struct iwl_firmware_pieces *pieces, enum iwl_ucode_type type, int sec, const void *data) { + alloc_sec_data(pieces, type, sec); + pieces->img[type].sec[sec].data = data; } @@ -303,6 +326,8 @@ static void set_sec_size(struct iwl_firmware_pieces *pieces, int sec, size_t size) { + alloc_sec_data(pieces, type, sec); + pieces->img[type].sec[sec].size = size; } @@ -318,6 +343,8 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces, int sec, u32 offset) { + alloc_sec_data(pieces, type, sec); + pieces->img[type].sec[sec].offset = offset; } @@ -383,6 +410,7 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces, struct fw_img_parsing *img; struct fw_sec *sec; struct fw_sec_parsing *sec_parse; + size_t alloc_size; if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX)) return -1; @@ -390,6 +418,13 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces, sec_parse = (struct fw_sec_parsing *)data; img = &pieces->img[type]; + + alloc_size = sizeof(*img->sec) * (img->sec_counter + 1); + sec = krealloc(img->sec, alloc_size, GFP_KERNEL); + if (!sec) + return -ENOMEM; + img->sec = sec; + sec = &img->sec[img->sec_counter]; sec->offset = le32_to_cpu(sec_parse->offset); @@ -1009,31 +1044,37 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, struct iwl_fw_dbg_mem_seg_tlv *dbg_mem = (void *)tlv_data; u32 type; + size_t size; + struct iwl_fw_dbg_mem_seg_tlv *n; if (tlv_len != (sizeof(*dbg_mem))) goto invalid_tlv_len; type = le32_to_cpu(dbg_mem->data_type); - drv->fw.dbg_dynamic_mem = true; - if (type >= ARRAY_SIZE(drv->fw.dbg_mem_tlv)) { - IWL_ERR(drv, - "Skip unknown dbg mem segment: %u\n", - dbg_mem->data_type); - break; - } + IWL_DEBUG_INFO(drv, "Found debug memory segment: %u\n", + dbg_mem->data_type); - if (pieces->dbg_mem_tlv[type]) { - IWL_ERR(drv, - "Ignore duplicate mem segment: %u\n", - dbg_mem->data_type); + switch (type & FW_DBG_MEM_TYPE_MASK) { + case FW_DBG_MEM_TYPE_REGULAR: + case FW_DBG_MEM_TYPE_PRPH: + /* we know how to handle these */ break; + default: + IWL_ERR(drv, + "Found debug memory segment with invalid type: 0x%x\n", + type); + return -EINVAL; } - IWL_DEBUG_INFO(drv, "Found debug memory segment: %u\n", - dbg_mem->data_type); - - pieces->dbg_mem_tlv[type] = dbg_mem; + size = sizeof(*pieces->dbg_mem_tlv) * + (pieces->n_dbg_mem_tlv + 1); + n = krealloc(pieces->dbg_mem_tlv, size, GFP_KERNEL); + if (!n) + return -ENOMEM; + pieces->dbg_mem_tlv = n; + pieces->dbg_mem_tlv[pieces->n_dbg_mem_tlv] = *dbg_mem; + pieces->n_dbg_mem_tlv++; break; } default: @@ -1083,12 +1124,18 @@ static int iwl_alloc_ucode(struct iwl_drv *drv, enum iwl_ucode_type type) { int i; - for (i = 0; - i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i); - i++) - if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]), - get_sec(pieces, type, i))) + struct fw_desc *sec; + + sec = kcalloc(pieces->img[type].sec_counter, sizeof(*sec), GFP_KERNEL); + if (!sec) + return -ENOMEM; + drv->fw.img[type].sec = sec; + drv->fw.img[type].num_sec = pieces->img[type].sec_counter; + + for (i = 0; i < pieces->img[type].sec_counter; i++) + if (iwl_alloc_fw_desc(drv, &sec[i], get_sec(pieces, type, i))) return -ENOMEM; + return 0; } @@ -1345,19 +1392,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) } } - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++) { - if (pieces->dbg_mem_tlv[i]) { - drv->fw.dbg_mem_tlv[i] = - kmemdup(pieces->dbg_mem_tlv[i], - sizeof(*drv->fw.dbg_mem_tlv[i]), - GFP_KERNEL); - if (!drv->fw.dbg_mem_tlv[i]) - goto out_free_fw; - } - } - /* Now that we can no longer fail, copy information */ + drv->fw.dbg_mem_tlv = pieces->dbg_mem_tlv; + pieces->dbg_mem_tlv = NULL; + drv->fw.n_dbg_mem_tlv = pieces->n_dbg_mem_tlv; + /* * The (size - 16) / 12 formula is based on the information recorded * for each event, which is of mode 1 (including timestamp) for all @@ -1441,25 +1481,27 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) op->name, err); #endif } - kfree(pieces); - return; + goto free; try_again: /* try next, if any */ release_firmware(ucode_raw); if (iwl_request_firmware(drv, false)) goto out_unbind; - kfree(pieces); - return; + goto free; out_free_fw: IWL_ERR(drv, "failed to allocate pci memory\n"); iwl_dealloc_ucode(drv); release_firmware(ucode_raw); out_unbind: - kfree(pieces); complete(&drv->request_firmware_complete); device_release_driver(drv->trans->dev); + free: + for (i = 0; i < ARRAY_SIZE(pieces->img); i++) + kfree(pieces->img[i].sec); + kfree(pieces->dbg_mem_tlv); + kfree(pieces); } struct iwl_drv *iwl_drv_start(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 84813b550ef1..d01701ee4777 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -379,7 +379,6 @@ enum iwl_ucode_tlv_capa { * For 16.0 uCode and above, there is no differentiation between sections, * just an offset to the HW address. */ -#define IWL_UCODE_SECTION_MAX 16 #define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC #define PAGING_SEPARATOR_SECTION 0xAAAABBBB @@ -489,25 +488,22 @@ enum iwl_fw_dbg_monitor_mode { }; /** - * enum iwl_fw_mem_seg_type - data types for dumping on error - * - * @FW_DBG_MEM_SMEM: the data type is SMEM - * @FW_DBG_MEM_DCCM_LMAC: the data type is DCCM_LMAC - * @FW_DBG_MEM_DCCM_UMAC: the data type is DCCM_UMAC + * enum iwl_fw_mem_seg_type - memory segment type + * @FW_DBG_MEM_TYPE_MASK: mask for the type indication + * @FW_DBG_MEM_TYPE_REGULAR: regular memory + * @FW_DBG_MEM_TYPE_PRPH: periphery memory (requires special reading) */ -enum iwl_fw_dbg_mem_seg_type { - FW_DBG_MEM_DCCM_LMAC = 0, - FW_DBG_MEM_DCCM_UMAC, - FW_DBG_MEM_SMEM, - - /* Must be last */ - FW_DBG_MEM_MAX, +enum iwl_fw_mem_seg_type { + FW_DBG_MEM_TYPE_MASK = 0xff000000, + FW_DBG_MEM_TYPE_REGULAR = 0x00000000, + FW_DBG_MEM_TYPE_PRPH = 0x01000000, }; /** * struct iwl_fw_dbg_mem_seg_tlv - configures the debug data memory segments * - * @data_type: enum %iwl_fw_mem_seg_type + * @data_type: the memory segment type to record, see &enum iwl_fw_mem_seg_type + * for what we care about * @ofs: the memory segment offset * @len: the memory segment length, in bytes * diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw.h index 5f229556339a..d323b70b510a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw.h @@ -132,7 +132,8 @@ struct fw_desc { }; struct fw_img { - struct fw_desc sec[IWL_UCODE_SECTION_MAX]; + struct fw_desc *sec; + int num_sec; bool is_dual_cpus; u32 paging_mem_size; }; @@ -295,8 +296,8 @@ struct iwl_fw { struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; - struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX]; - bool dbg_dynamic_mem; + struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv; + size_t n_dbg_mem_tlv; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; u8 dbg_dest_reg_num; struct iwl_gscan_capabilities gscan_capa; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index b88e2048ae0b..207d8ae1e116 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1262,12 +1262,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, iwl_trans_d3_suspend(mvm->trans, test, !unified_image); out: if (ret < 0) { - iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); - if (mvm->restart_fw > 0) { - mvm->restart_fw--; - ieee80211_restart_hw(mvm->hw); - } iwl_mvm_free_nd(mvm); + + if (!unified_image) { + iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); + if (mvm->restart_fw > 0) { + mvm->restart_fw--; + ieee80211_restart_hw(mvm->hw); + } + } } out_noreset: mutex_unlock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 7b7d2a146e30..a260cd503200 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -798,7 +798,7 @@ static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file, static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) { - int ret; + int __maybe_unused ret; mutex_lock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index ae12badc0c2a..567597c26115 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -2075,7 +2075,7 @@ struct iwl_mu_group_mgmt_notif { * @system_time: system time on air rise * @tsf: TSF on air rise * @beacon_timestamp: beacon on air rise - * @phy_flags: general phy flags: band, modulation, etc. + * @band: band, matches &RX_RES_PHY_FLAGS_BAND_24 definition * @channel: channel this beacon was received on * @rates: rate in ucode internal format * @byte_count: frame's byte count @@ -2084,12 +2084,12 @@ struct iwl_stored_beacon_notif { __le32 system_time; __le64 tsf; __le32 beacon_timestamp; - __le16 phy_flags; + __le16 band; __le16 channel; __le32 rates; __le32 byte_count; u8 data[MAX_STORED_BEACON_SIZE]; -} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */ +} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_2 */ #define LQM_NUMBER_OF_STATIONS_IN_REPORT 16 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 2e8e3e8e30a3..e7b3b712d778 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -406,46 +406,63 @@ static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = { { .start = 0x00a02400, .end = 0x00a02758 }, }; -static u32 iwl_dump_prph(struct iwl_trans *trans, - struct iwl_fw_error_dump_data **data, - const struct iwl_prph_range *iwl_prph_dump_addr, - u32 range_len) +static void _iwl_read_prph_block(struct iwl_trans *trans, u32 start, + u32 len_bytes, __le32 *data) +{ + u32 i; + + for (i = 0; i < len_bytes; i += 4) + *data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i)); +} + +static bool iwl_read_prph_block(struct iwl_trans *trans, u32 start, + u32 len_bytes, __le32 *data) +{ + unsigned long flags; + bool success = false; + + if (iwl_trans_grab_nic_access(trans, &flags)) { + success = true; + _iwl_read_prph_block(trans, start, len_bytes, data); + iwl_trans_release_nic_access(trans, &flags); + } + + return success; +} + +static void iwl_dump_prph(struct iwl_trans *trans, + struct iwl_fw_error_dump_data **data, + const struct iwl_prph_range *iwl_prph_dump_addr, + u32 range_len) { struct iwl_fw_error_dump_prph *prph; unsigned long flags; - u32 prph_len = 0, i; + u32 i; if (!iwl_trans_grab_nic_access(trans, &flags)) - return 0; + return; for (i = 0; i < range_len; i++) { /* The range includes both boundaries */ int num_bytes_in_chunk = iwl_prph_dump_addr[i].end - iwl_prph_dump_addr[i].start + 4; - int reg; - __le32 *val; - - prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk; (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); (*data)->len = cpu_to_le32(sizeof(*prph) + num_bytes_in_chunk); prph = (void *)(*data)->data; prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start); - val = (void *)prph->data; - for (reg = iwl_prph_dump_addr[i].start; - reg <= iwl_prph_dump_addr[i].end; - reg += 4) - *val++ = cpu_to_le32(iwl_read_prph_no_grab(trans, - reg)); + _iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start, + /* our range is inclusive, hence + 4 */ + iwl_prph_dump_addr[i].end - + iwl_prph_dump_addr[i].start + 4, + (void *)prph->data); *data = iwl_fw_error_next_data(*data); } iwl_trans_release_nic_access(trans, &flags); - - return prph_len; } /* @@ -495,11 +512,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) struct iwl_mvm_dump_ptrs *fw_error_dump; struct scatterlist *sg_dump_data; u32 sram_len, sram_ofs; - struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem = - mvm->fw->dbg_mem_tlv; + const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = mvm->fw->dbg_mem_tlv; u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0; - u32 smem_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->smem_len; - u32 sram2_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->dccm2_len; + u32 smem_len = mvm->fw->n_dbg_mem_tlv ? 0 : mvm->cfg->smem_len; + u32 sram2_len = mvm->fw->n_dbg_mem_tlv ? 0 : mvm->cfg->dccm2_len; bool monitor_dump_only = false; int i; @@ -624,10 +640,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; /* Make room for MEM segments */ - for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) { - if (fw_dbg_mem[i]) - file_len += sizeof(*dump_data) + sizeof(*dump_mem) + - le32_to_cpu(fw_dbg_mem[i]->len); + for (i = 0; i < mvm->fw->n_dbg_mem_tlv; i++) { + file_len += sizeof(*dump_data) + sizeof(*dump_mem) + + le32_to_cpu(fw_dbg_mem[i].len); } /* Make room for fw's virtual image pages, if it exists */ @@ -656,7 +671,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) file_len += sizeof(*dump_data) + sizeof(*dump_trig) + mvm->fw_dump_desc->len; - if (!mvm->fw->dbg_dynamic_mem) + if (!mvm->fw->n_dbg_mem_tlv) file_len += sram_len + sizeof(*dump_mem); dump_file = vzalloc(file_len); @@ -708,7 +723,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (monitor_dump_only) goto dump_trans_data; - if (!mvm->fw->dbg_dynamic_mem) { + if (!mvm->fw->n_dbg_mem_tlv) { dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); dump_mem = (void *)dump_data->data; @@ -719,22 +734,39 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_data = iwl_fw_error_next_data(dump_data); } - for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) { - if (fw_dbg_mem[i]) { - u32 len = le32_to_cpu(fw_dbg_mem[i]->len); - u32 ofs = le32_to_cpu(fw_dbg_mem[i]->ofs); - - dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - dump_data->len = cpu_to_le32(len + - sizeof(*dump_mem)); - dump_mem = (void *)dump_data->data; - dump_mem->type = fw_dbg_mem[i]->data_type; - dump_mem->offset = cpu_to_le32(ofs); + for (i = 0; i < mvm->fw->n_dbg_mem_tlv; i++) { + u32 len = le32_to_cpu(fw_dbg_mem[i].len); + u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs); + bool success; + + dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); + dump_data->len = cpu_to_le32(len + sizeof(*dump_mem)); + dump_mem = (void *)dump_data->data; + dump_mem->type = fw_dbg_mem[i].data_type; + dump_mem->offset = cpu_to_le32(ofs); + + switch (dump_mem->type & cpu_to_le32(FW_DBG_MEM_TYPE_MASK)) { + case cpu_to_le32(FW_DBG_MEM_TYPE_REGULAR): iwl_trans_read_mem_bytes(mvm->trans, ofs, dump_mem->data, len); - dump_data = iwl_fw_error_next_data(dump_data); + success = true; + break; + case cpu_to_le32(FW_DBG_MEM_TYPE_PRPH): + success = iwl_read_prph_block(mvm->trans, ofs, len, + (void *)dump_mem->data); + break; + default: + /* + * shouldn't get here, we ignored this kind + * of TLV earlier during the TLV parsing?! + */ + WARN_ON(1); + success = false; } + + if (success) + dump_data = iwl_fw_error_next_data(dump_data); } if (smem_len) { @@ -816,11 +848,12 @@ dump_trans_data: sg_nents(sg_dump_data), fw_error_dump->op_mode_ptr, fw_error_dump->op_mode_len, 0); - sg_pcopy_from_buffer(sg_dump_data, - sg_nents(sg_dump_data), - fw_error_dump->trans_ptr->data, - fw_error_dump->trans_ptr->len, - fw_error_dump->op_mode_len); + if (fw_error_dump->trans_ptr) + sg_pcopy_from_buffer(sg_dump_data, + sg_nents(sg_dump_data), + fw_error_dump->trans_ptr->data, + fw_error_dump->trans_ptr->len, + fw_error_dump->op_mode_len); dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len, GFP_KERNEL); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 872066317fa5..b278e44e97ad 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -190,7 +190,7 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) * CPU2 paging CSS * CPU2 paging image (including instruction and data) */ - for (sec_idx = 0; sec_idx < IWL_UCODE_SECTION_MAX; sec_idx++) { + for (sec_idx = 0; sec_idx < image->num_sec; sec_idx++) { if (image->sec[sec_idx].offset == PAGING_SEPARATOR_SECTION) { sec_idx++; break; @@ -201,7 +201,7 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) * If paging is enabled there should be at least 2 more sections left * (one for CSS and one for Paging data) */ - if (sec_idx >= ARRAY_SIZE(image->sec) - 1) { + if (sec_idx >= image->num_sec - 1) { IWL_ERR(mvm, "Paging: Missing CSS and/or paging sections\n"); iwl_free_fw_paging(mvm); return -EINVAL; @@ -259,9 +259,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm, { struct page *block; dma_addr_t phys = 0; - int blk_idx = 0; - int order, num_of_pages; - int dma_enabled; + int blk_idx, order, num_of_pages, size, dma_enabled; if (mvm->fw_paging_db[0].fw_paging_block) return 0; @@ -272,9 +270,8 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm, BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE); num_of_pages = image->paging_mem_size / FW_PAGING_SIZE; - mvm->num_of_paging_blk = ((num_of_pages - 1) / - NUM_OF_PAGE_PER_GROUP) + 1; - + mvm->num_of_paging_blk = + DIV_ROUND_UP(num_of_pages, NUM_OF_PAGE_PER_GROUP); mvm->num_of_pages_in_last_blk = num_of_pages - NUM_OF_PAGE_PER_GROUP * (mvm->num_of_paging_blk - 1); @@ -284,46 +281,13 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm, mvm->num_of_paging_blk, mvm->num_of_pages_in_last_blk); - /* allocate block of 4Kbytes for paging CSS */ - order = get_order(FW_PAGING_SIZE); - block = alloc_pages(GFP_KERNEL, order); - if (!block) { - /* free all the previous pages since we failed */ - iwl_free_fw_paging(mvm); - return -ENOMEM; - } - - mvm->fw_paging_db[blk_idx].fw_paging_block = block; - mvm->fw_paging_db[blk_idx].fw_paging_size = FW_PAGING_SIZE; - - if (dma_enabled) { - phys = dma_map_page(mvm->trans->dev, block, 0, - PAGE_SIZE << order, DMA_BIDIRECTIONAL); - if (dma_mapping_error(mvm->trans->dev, phys)) { - /* - * free the previous pages and the current one since - * we failed to map_page. - */ - iwl_free_fw_paging(mvm); - return -ENOMEM; - } - mvm->fw_paging_db[blk_idx].fw_paging_phys = phys; - } else { - mvm->fw_paging_db[blk_idx].fw_paging_phys = PAGING_ADDR_SIG | - blk_idx << BLOCK_2_EXP_SIZE; - } - - IWL_DEBUG_FW(mvm, - "Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n", - order); - /* - * allocate blocks in dram. - * since that CSS allocated in fw_paging_db[0] loop start from index 1 + * Allocate CSS and paging blocks in dram. */ - for (blk_idx = 1; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) { - /* allocate block of PAGING_BLOCK_SIZE (32K) */ - order = get_order(PAGING_BLOCK_SIZE); + for (blk_idx = 0; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) { + /* For CSS allocate 4KB, for others PAGING_BLOCK_SIZE (32K) */ + size = blk_idx ? PAGING_BLOCK_SIZE : FW_PAGING_SIZE; + order = get_order(size); block = alloc_pages(GFP_KERNEL, order); if (!block) { /* free all the previous pages since we failed */ @@ -332,7 +296,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm, } mvm->fw_paging_db[blk_idx].fw_paging_block = block; - mvm->fw_paging_db[blk_idx].fw_paging_size = PAGING_BLOCK_SIZE; + mvm->fw_paging_db[blk_idx].fw_paging_size = size; if (dma_enabled) { phys = dma_map_page(mvm->trans->dev, block, 0, @@ -353,9 +317,14 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm, blk_idx << BLOCK_2_EXP_SIZE; } - IWL_DEBUG_FW(mvm, - "Paging: allocated 32K bytes (order %d) for firmware paging.\n", - order); + if (!blk_idx) + IWL_DEBUG_FW(mvm, + "Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n", + order); + else + IWL_DEBUG_FW(mvm, + "Paging: allocated 32K bytes (order %d) for firmware paging.\n", + order); } return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 4a0874e40731..ebf6c071eb36 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1565,7 +1565,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, rx_status.flag |= RX_FLAG_MACTIME_PLCP_START; rx_status.device_timestamp = le32_to_cpu(sb->system_time); rx_status.band = - (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? + (sb->band & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; rx_status.freq = ieee80211_channel_to_frequency(le16_to_cpu(sb->channel), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 45122dafe922..71f9aa9f7c7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -463,6 +463,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) IEEE80211_RADIOTAP_MCS_HAVE_STBC; hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC | IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US | + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ; + /* this is the case for CCK frames, it's better (only 8) for OFDM */ + hw->radiotap_timestamp.accuracy = 22; + hw->rate_control_algorithm = "iwl-mvm-rs"; hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; @@ -670,7 +677,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->wowlan = &mvm->wowlan; } - if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && + if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec && mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_resume && device_can_wakeup(mvm->trans->dev)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 4a9cb76b7611..a672aa71c656 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1657,8 +1657,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, * Disable a TXQ. * Note that in non-DQA mode the %mac80211_queue and %tid params are ignored. */ -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u8 tid, u8 flags); +int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 tid, u8 flags); int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq); /* Return a bitmask with all the hw supported queues, except for the diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 227c5ed9cbe6..80f99c365b6a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -161,9 +161,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct rs_rate *rate, const struct rs_tx_column *next_col) { - struct iwl_mvm_sta *mvmsta; - struct iwl_mvm_vif *mvmvif; - if (!sta->ht_cap.ht_supported) return false; @@ -176,9 +173,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) return false; - mvmsta = iwl_mvm_sta_from_mac80211(sta); - mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); - if (mvm->nvm_data->sku_cap_mimo_disabled) return false; @@ -3071,7 +3065,7 @@ static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm) void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) { - u8 nss = 0, mcs = 0; + u8 nss = 0; spin_lock(&mvm->drv_stats_lock); @@ -3099,11 +3093,9 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) if (rate & RATE_MCS_HT_MSK) { mvm->drv_rx_stats.ht_frames++; - mcs = rate & RATE_HT_MCS_RATE_CODE_MSK; nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; } else if (rate & RATE_MCS_VHT_MSK) { mvm->drv_rx_stats.vht_frames++; - mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; } else { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 0e60e38b2acf..e16687d5afaa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -621,12 +621,10 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, }; int expected_size = iwl_mvm_has_new_rx_api(mvm) ? sizeof(*stats) : sizeof(struct iwl_notif_statistics_v10); - u32 temperature; if (iwl_rx_packet_payload_len(pkt) != expected_size) goto invalid; - temperature = le32_to_cpu(stats->general.radio_temperature); data.mac_id = stats->rx.general.mac_id; data.beacon_filter_average_energy = stats->general.beacon_filter_average_energy; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 636c8b03e318..40e7fc5f1f1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -454,13 +454,6 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue) rcu_read_unlock(); - spin_lock_bh(&mvm->queue_info_lock); - /* Unmap MAC queues and TIDs from this queue */ - mvm->queue_info[queue].hw_queue_to_mac80211 = 0; - mvm->queue_info[queue].hw_queue_refcount = 0; - mvm->queue_info[queue].tid_bitmap = 0; - spin_unlock_bh(&mvm->queue_info_lock); - return disable_agg_tids; } @@ -755,28 +748,22 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, * first */ if (using_inactive_queue) { - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .action = SCD_CFG_DISABLE_QUEUE, - }; - u8 txq_curr_ac; - - disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue); + u8 txq_curr_ac, sta_id; spin_lock_bh(&mvm->queue_info_lock); txq_curr_ac = mvm->queue_info[queue].mac80211_ac; - cmd.sta_id = mvm->queue_info[queue].ra_sta_id; - cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac]; - cmd.tid = mvm->queue_info[queue].txq_tid; + sta_id = mvm->queue_info[queue].ra_sta_id; spin_unlock_bh(&mvm->queue_info_lock); + disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue); /* Disable the queue */ if (disable_agg_tids) iwl_mvm_invalidate_sta_queue(mvm, queue, disable_agg_tids, false); - iwl_trans_txq_disable(mvm->trans, queue, false); - ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), - &cmd); + + ret = iwl_mvm_disable_txq(mvm, queue, + mvmsta->vif->hw_queue[txq_curr_ac], + tid, 0); if (ret) { IWL_ERR(mvm, "Failed to free inactive queue %d (ret=%d)\n", @@ -791,7 +778,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, } /* If TXQ is allocated to another STA, update removal in FW */ - if (cmd.sta_id != mvmsta->sta_id) + if (sta_id != mvmsta->sta_id) iwl_mvm_invalidate_sta_queue(mvm, queue, 0, true); } @@ -868,7 +855,6 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue) .scd_queue = queue, .action = SCD_CFG_UPDATE_QUEUE_TID, }; - s8 sta_id; int tid; unsigned long tid_bitmap; int ret; @@ -876,7 +862,6 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue) lockdep_assert_held(&mvm->mutex); spin_lock_bh(&mvm->queue_info_lock); - sta_id = mvm->queue_info[queue].ra_sta_id; tid_bitmap = mvm->queue_info[queue].tid_bitmap; spin_unlock_bh(&mvm->queue_info_lock); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 66957ac12ca4..2b2db38eee3e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -102,14 +102,13 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr, #define OPT_HDR(type, skb, off) \ (type *)(skb_network_header(skb) + (off)) -static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, - struct ieee80211_hdr *hdr, - struct ieee80211_tx_info *info, - struct iwl_tx_cmd *tx_cmd) +static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_hdr *hdr, + struct ieee80211_tx_info *info) { + u16 offload_assist = 0; #if IS_ENABLED(CONFIG_INET) u16 mh_len = ieee80211_hdrlen(hdr->frame_control); - u16 offload_assist = le16_to_cpu(tx_cmd->offload_assist); u8 protocol = 0; /* @@ -117,7 +116,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, * compute it */ if (skb->ip_summed != CHECKSUM_PARTIAL || IWL_MVM_SW_TX_CSUM_OFFLOAD) - return; + goto out; /* We do not expect to be requested to csum stuff we do not support */ if (WARN_ONCE(!(mvm->hw->netdev_features & IWL_TX_CSUM_NETIF_FLAGS) || @@ -125,7 +124,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, skb->protocol != htons(ETH_P_IPV6)), "No support for requested checksum\n")) { skb_checksum_help(skb); - return; + goto out; } if (skb->protocol == htons(ETH_P_IP)) { @@ -145,7 +144,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, protocol != NEXTHDR_HOP && protocol != NEXTHDR_DEST) { skb_checksum_help(skb); - return; + goto out; } hp = OPT_HDR(struct ipv6_opt_hdr, skb, off); @@ -159,7 +158,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) { WARN_ON_ONCE(1); skb_checksum_help(skb); - return; + goto out; } /* enable L4 csum */ @@ -191,8 +190,9 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, mh_len /= 2; offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE; - tx_cmd->offload_assist = cpu_to_le16(offload_assist); +out: #endif + return offload_assist; } /* @@ -295,7 +295,52 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, !(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU)))) tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD)); - iwl_mvm_tx_csum(mvm, skb, hdr, info, tx_cmd); + tx_cmd->offload_assist |= + cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info)); +} + +static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta) +{ + int rate_idx; + u8 rate_plcp; + u32 rate_flags; + + /* HT rate doesn't make sense for a non data frame */ + WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, + "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame\n", + info->control.rates[0].flags, + info->control.rates[0].idx); + + rate_idx = info->control.rates[0].idx; + /* if the rate isn't a well known legacy rate, take the lowest one */ + if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY) + rate_idx = rate_lowest_index( + &mvm->nvm_data->bands[info->band], sta); + + /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ + if (info->band == NL80211_BAND_5GHZ) + rate_idx += IWL_FIRST_OFDM_RATE; + + /* For 2.4 GHZ band, check that there is no need to remap */ + BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0); + + /* Get PLCP rate for tx_cmd->rate_n_flags */ + rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); + + if (info->band == NL80211_BAND_2GHZ && + !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) + rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS; + else + rate_flags = + BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; + + /* Set CCK flag as needed */ + if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) + rate_flags |= RATE_MCS_CCK_MSK; + + return (u32)rate_plcp | rate_flags; } /* @@ -305,10 +350,6 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, __le16 fc) { - u32 rate_flags; - int rate_idx; - u8 rate_plcp; - /* Set retry limit on RTS packets */ tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT; @@ -337,46 +378,12 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR); } - /* HT rate doesn't make sense for a non data frame */ - WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, - "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n", - info->control.rates[0].flags, - info->control.rates[0].idx, - le16_to_cpu(fc)); - - rate_idx = info->control.rates[0].idx; - /* if the rate isn't a well known legacy rate, take the lowest one */ - if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY) - rate_idx = rate_lowest_index( - &mvm->nvm_data->bands[info->band], sta); - - /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == NL80211_BAND_5GHZ) - rate_idx += IWL_FIRST_OFDM_RATE; - - /* For 2.4 GHZ band, check that there is no need to remap */ - BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0); - - /* Get PLCP rate for tx_cmd->rate_n_flags */ - rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); - mvm->mgmt_last_antenna_idx = iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm), mvm->mgmt_last_antenna_idx); - if (info->band == NL80211_BAND_2GHZ && - !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) - rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS; - else - rate_flags = - BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; - - /* Set CCK flag as needed */ - if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) - rate_flags |= RATE_MCS_CCK_MSK; - /* Set the rate in the TX cmd */ - tx_cmd->rate_n_flags = cpu_to_le32((u32)rate_plcp | rate_flags); + tx_cmd->rate_n_flags = cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta)); } static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index d04babd99b53..26b853ef195f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -693,10 +693,6 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, .tid = cfg->tid, }; - /* Set sta_id in the command, if it exists */ - if (iwl_mvm_is_dqa_supported(mvm)) - cmd.sta_id = cfg->sta_id; - iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), @@ -706,8 +702,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, } } -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u8 tid, u8 flags) +int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 tid, u8 flags) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, @@ -720,7 +716,7 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { spin_unlock_bh(&mvm->queue_info_lock); - return; + return 0; } mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); @@ -760,7 +756,7 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, /* If the queue is still enabled - nothing left to do in this func */ if (cmd.action == SCD_CFG_ENABLE_QUEUE) { spin_unlock_bh(&mvm->queue_info_lock); - return; + return 0; } cmd.sta_id = mvm->queue_info[queue].ra_sta_id; @@ -791,6 +787,8 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, if (ret) IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", queue, ret); + + return ret; } /** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b10e3633df1a..c1d99d15796d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -805,7 +805,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, (*first_ucode_section)++; } - for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) { + for (i = *first_ucode_section; i < image->num_sec; i++) { last_read_idx = i; /* @@ -868,19 +868,15 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans, int cpu, int *first_ucode_section) { - int shift_param; int i, ret = 0; u32 last_read_idx = 0; - if (cpu == 1) { - shift_param = 0; + if (cpu == 1) *first_ucode_section = 0; - } else { - shift_param = 16; + else (*first_ucode_section)++; - } - for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) { + for (i = *first_ucode_section; i < image->num_sec; i++) { last_read_idx = i; /* @@ -1066,6 +1062,20 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans, &first_ucode_section); } +static bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans) +{ + bool hw_rfkill = iwl_is_rfkill_set(trans); + + if (hw_rfkill) + set_bit(STATUS_RFKILL, &trans->status); + else + clear_bit(STATUS_RFKILL, &trans->status); + + iwl_trans_pcie_rf_kill(trans, hw_rfkill); + + return hw_rfkill; +} + static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1208,12 +1218,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, mutex_lock(&trans_pcie->mutex); /* If platform's RF_KILL switch is NOT set to KILL */ - hw_rfkill = iwl_is_rfkill_set(trans); - if (hw_rfkill) - set_bit(STATUS_RFKILL, &trans->status); - else - clear_bit(STATUS_RFKILL, &trans->status); - iwl_trans_pcie_rf_kill(trans, hw_rfkill); + hw_rfkill = iwl_trans_check_hw_rf_kill(trans); if (hw_rfkill && !run_in_rfkill) { ret = -ERFKILL; goto out; @@ -1261,13 +1266,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, ret = iwl_pcie_load_given_ucode(trans, fw); /* re-check RF-Kill state since we may have missed the interrupt */ - hw_rfkill = iwl_is_rfkill_set(trans); - if (hw_rfkill) - set_bit(STATUS_RFKILL, &trans->status); - else - clear_bit(STATUS_RFKILL, &trans->status); - - iwl_trans_pcie_rf_kill(trans, hw_rfkill); + hw_rfkill = iwl_trans_check_hw_rf_kill(trans); if (hw_rfkill && !run_in_rfkill) ret = -ERFKILL; @@ -1659,7 +1658,6 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - bool hw_rfkill; int err; lockdep_assert_held(&trans_pcie->mutex); @@ -1683,13 +1681,8 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) /* Set is_down to false here so that...*/ trans_pcie->is_down = false; - hw_rfkill = iwl_is_rfkill_set(trans); - if (hw_rfkill) - set_bit(STATUS_RFKILL, &trans->status); - else - clear_bit(STATUS_RFKILL, &trans->status); - /* ... rfkill can call stop_device and set it false if needed */ - iwl_trans_pcie_rf_kill(trans, hw_rfkill); + /* ...rfkill can call stop_device and set it false if needed */ + iwl_trans_check_hw_rf_kill(trans); /* Make sure we sync here, because we'll need full access later */ if (low_power) diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 301170cccfff..033ff881c751 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -305,7 +305,7 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return 0; + return ret; } static int lbs_wait_for_ds_awake(struct lbs_private *priv) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c index c47d6366875d..a75013ac84d7 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c @@ -101,13 +101,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, { struct txpd *local_tx_pd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - unsigned int pad; - int headroom = (priv->adapter->iface_type == - MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; - - pad = ((void *)skb->data - sizeof(*local_tx_pd) - - headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); - skb_push(skb, pad); skb_push(skb, sizeof(*local_tx_pd)); @@ -121,12 +114,10 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, local_tx_pd->bss_num = priv->bss_num; local_tx_pd->bss_type = priv->bss_type; /* Always zero as the data is followed by struct txpd */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + - pad); + local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - - sizeof(*local_tx_pd) - - pad); + sizeof(*local_tx_pd)); if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; @@ -190,7 +181,11 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ra_list_flags); return -1; } - skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN); + + /* skb_aggr->data already 64 byte align, just reserve bus interface + * header and txpd. + */ + skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index b9284b533294..ae2b69db5994 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -114,7 +114,8 @@ mwifiex_info_read(struct file *file, char __user *ubuf, if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); - p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); + p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len, + info.ssid.ssid); p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "country_code = \"%s\"\n", info.country_code); diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 55db158fd156..cb6a1a81d44e 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -550,6 +550,7 @@ enum mwifiex_channel_flags { #define EVENT_TX_DATA_PAUSE 0x00000055 #define EVENT_EXT_SCAN_REPORT 0x00000058 #define EVENT_RXBA_SYNC 0x00000059 +#define EVENT_UNKNOWN_DEBUG 0x00000063 #define EVENT_BG_SCAN_STOPPED 0x00000065 #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_MULTI_CHAN_INFO 0x0000006a diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 0e89ccfa244e..756948385b60 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -409,8 +409,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) static void mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) { - int idx; - if (!adapter) { pr_err("%s: adapter is NULL\n", __func__); return; @@ -428,23 +426,6 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n"); mwifiex_free_cmd_buffer(adapter); - for (idx = 0; idx < adapter->num_mem_types; idx++) { - struct memory_type_mapping *entry = - &adapter->mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } - if (adapter->sleep_cfm) dev_kfree_skb_any(adapter->sleep_cfm); } @@ -657,10 +638,9 @@ void mwifiex_free_priv(struct mwifiex_private *priv) * - Free the adapter * - Notify completion */ -int +void mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) { - int ret = -EINPROGRESS; struct mwifiex_private *priv; s32 i; unsigned long flags; @@ -668,15 +648,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) /* mwifiex already shutdown */ if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) - return 0; - - adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING; - /* wait for mwifiex_process to complete */ - if (adapter->mwifiex_processing) { - mwifiex_dbg(adapter, WARN, - "main process is still running\n"); - return ret; - } + return; /* cancel current command */ if (adapter->curr_cmd) { @@ -727,11 +699,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) mwifiex_adapter_cleanup(adapter); spin_unlock(&adapter->mwifiex_lock); - - /* Notify completion */ - ret = mwifiex_shutdown_fw_complete(adapter); - - return ret; + adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; } /* diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index e5c3a8aa3929..9d80180a5519 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -248,15 +248,14 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) if (adapter->mwifiex_processing || adapter->main_locked) { adapter->more_task_flag = true; spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - goto exit_main_proc; + return 0; } else { adapter->mwifiex_processing = true; spin_unlock_irqrestore(&adapter->main_proc_lock, flags); } process_start: do { - if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) || - (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) + if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) break; /* For non-USB interfaces, If we process interrupts first, it @@ -464,9 +463,6 @@ process_start: adapter->mwifiex_processing = false; spin_unlock_irqrestore(&adapter->main_proc_lock, flags); -exit_main_proc: - if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) - mwifiex_shutdown_drv(adapter); return ret; } EXPORT_SYMBOL_GPL(mwifiex_main_process); @@ -645,16 +641,14 @@ err_dnld_fw: if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); + adapter->surprise_removed = true; + mwifiex_terminate_workqueue(adapter); + if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { pr_debug("info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); + mwifiex_shutdown_drv(adapter); } - adapter->surprise_removed = true; - mwifiex_terminate_workqueue(adapter); + init_failed = true; done: if (adapter->cal_data) { @@ -1032,7 +1026,7 @@ void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter) } EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync); -void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) +int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info) { void *p; char drv_version[64]; @@ -1042,21 +1036,17 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) int i, idx; struct netdev_queue *txq; struct mwifiex_debug_info *debug_info; - - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } + void *drv_info_dump; mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n"); - adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX); + /* memory allocate here should be free in mwifiex_upload_device_dump*/ + drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX); - if (!adapter->drv_info_dump) - return; + if (!drv_info_dump) + return 0; - p = (char *)(adapter->drv_info_dump); + p = (char *)(drv_info_dump); p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); mwifiex_drv_get_driver_version(adapter, drv_version, @@ -1140,18 +1130,20 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) kfree(debug_info); } - adapter->drv_info_size = p - adapter->drv_info_dump; mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n"); + *drv_info = drv_info_dump; + return p - drv_info_dump; } EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump); -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter) +void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info, + int drv_info_size) { u8 idx, *dump_data, *fw_dump_ptr; u32 dump_len; dump_len = (strlen("========Start dump driverinfo========\n") + - adapter->drv_info_size + + drv_info_size + strlen("\n========End dump========\n")); for (idx = 0; idx < adapter->num_mem_types; idx++) { @@ -1181,8 +1173,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter) strcpy(fw_dump_ptr, "========Start dump driverinfo========\n"); fw_dump_ptr += strlen("========Start dump driverinfo========\n"); - memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size); - fw_dump_ptr += adapter->drv_info_size; + memcpy(fw_dump_ptr, drv_info, drv_info_size); + fw_dump_ptr += drv_info_size; strcpy(fw_dump_ptr, "\n========End dump========\n"); fw_dump_ptr += strlen("\n========End dump========\n"); @@ -1220,18 +1212,12 @@ done: struct memory_type_mapping *entry = &adapter->mem_type_mapping_tbl[idx]; - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } + vfree(entry->mem_ptr); + entry->mem_ptr = NULL; entry->mem_size = 0; } - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } + vfree(drv_info); } EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump); @@ -1362,7 +1348,7 @@ static void mwifiex_main_work_queue(struct work_struct *work) * This function gets called during PCIe function level reset. Required * code is extracted from mwifiex_remove_card() */ -static int +int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter) { struct mwifiex_private *priv; @@ -1399,11 +1385,8 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter) } mwifiex_dbg(adapter, CMD, "cmd: calling mwifiex_shutdown_drv...\n"); - adapter->init_wait_q_woken = false; - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); + mwifiex_shutdown_drv(adapter); if (adapter->if_ops.down_dev) adapter->if_ops.down_dev(adapter); @@ -1434,24 +1417,18 @@ mwifiex_shutdown_sw(struct mwifiex_adapter *adapter) exit_return: return 0; } +EXPORT_SYMBOL_GPL(mwifiex_shutdown_sw); /* This function gets called during PCIe function level reset. Required * code is extracted from mwifiex_add_card() */ -static int -mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct completion *fw_done, - struct mwifiex_if_ops *if_ops, u8 iface_type) +int +mwifiex_reinit_sw(struct mwifiex_adapter *adapter) { - char fw_name[32]; - struct pcie_service_card *card = adapter->card; - mwifiex_init_lock_list(adapter); if (adapter->if_ops.up_dev) adapter->if_ops.up_dev(adapter); - adapter->iface_type = iface_type; - adapter->fw_done = fw_done; - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; adapter->surprise_removed = false; init_waitqueue_head(&adapter->init_wait_q); @@ -1488,18 +1465,12 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter, struct completion *fw_done, * mwifiex_register_dev() */ mwifiex_dbg(adapter, INFO, "%s, mwifiex_init_hw_fw()...\n", __func__); - strcpy(fw_name, adapter->fw_name); - strcpy(adapter->fw_name, PCIE8997_DEFAULT_WIFIFW_NAME); - adapter->tx_buf_size = card->pcie.tx_buf_size; - adapter->ext_scan = card->pcie.can_ext_scan; if (mwifiex_init_hw_fw(adapter, false)) { - strcpy(adapter->fw_name, fw_name); mwifiex_dbg(adapter, ERROR, "%s: firmware init failed\n", __func__); goto err_init_fw; } - strcpy(adapter->fw_name, fw_name); mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); complete_all(adapter->fw_done); @@ -1509,43 +1480,22 @@ err_init_fw: mwifiex_dbg(adapter, ERROR, "info: %s: unregister device\n", __func__); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); + +err_kmalloc: + adapter->surprise_removed = true; + mwifiex_terminate_workqueue(adapter); if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { mwifiex_dbg(adapter, ERROR, "info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); + mwifiex_shutdown_drv(adapter); } -err_kmalloc: - mwifiex_terminate_workqueue(adapter); - adapter->surprise_removed = true; complete_all(adapter->fw_done); mwifiex_dbg(adapter, INFO, "%s, error\n", __func__); return -1; } - -/* This function processes pre and post PCIe function level resets. - * It performs software cleanup without touching PCIe specific code. - * Also, during initialization PCIe stuff is skipped. - */ -void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare) -{ - struct mwifiex_if_ops if_ops; - - if (!prepare) { - mwifiex_reinit_sw(adapter, adapter->fw_done, &if_ops, - adapter->iface_type); - } else { - memcpy(&if_ops, &adapter->if_ops, - sizeof(struct mwifiex_if_ops)); - mwifiex_shutdown_sw(adapter); - } -} -EXPORT_SYMBOL_GPL(mwifiex_do_flr); +EXPORT_SYMBOL_GPL(mwifiex_reinit_sw); static irqreturn_t mwifiex_irq_wakeup_handler(int irq, void *priv) { @@ -1681,17 +1631,13 @@ err_init_fw: pr_debug("info: %s: unregister device\n", __func__); if (adapter->if_ops.unregister_dev) adapter->if_ops.unregister_dev(adapter); - if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { - pr_debug("info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - } err_registerdev: adapter->surprise_removed = true; mwifiex_terminate_workqueue(adapter); + if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { + pr_debug("info: %s: shutdown mwifiex\n", __func__); + mwifiex_shutdown_drv(adapter); + } err_kmalloc: mwifiex_free_adapter(adapter); @@ -1741,11 +1687,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, CMD, "cmd: calling mwifiex_shutdown_drv...\n"); - adapter->init_wait_q_woken = false; - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); + mwifiex_shutdown_drv(adapter); mwifiex_dbg(adapter, CMD, "cmd: mwifiex_shutdown_drv done\n"); if (atomic_read(&adapter->rx_pending) || diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index d552a9d104d0..5c8297207f33 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -248,7 +248,6 @@ enum MWIFIEX_HARDWARE_STATUS { MWIFIEX_HW_STATUS_INITIALIZING, MWIFIEX_HW_STATUS_INIT_DONE, MWIFIEX_HW_STATUS_RESET, - MWIFIEX_HW_STATUS_CLOSING, MWIFIEX_HW_STATUS_NOT_READY }; @@ -995,8 +994,6 @@ struct mwifiex_adapter { u8 key_api_major_ver, key_api_minor_ver; struct memory_type_mapping *mem_type_mapping_tbl; u8 num_mem_types; - void *drv_info_dump; - u32 drv_info_size; bool scan_chan_gap_enabled; struct sk_buff_head rx_data_q; bool mfg_mode; @@ -1041,9 +1038,7 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter); int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); -int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); - -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); +void mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); @@ -1644,8 +1639,9 @@ void mwifiex_hist_data_add(struct mwifiex_private *priv, u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, u8 rx_rate, u8 ht_info); -void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); +int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info); +void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info, + int drv_info_size); void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, @@ -1670,5 +1666,6 @@ void mwifiex_debugfs_remove(void); void mwifiex_dev_debugfs_init(struct mwifiex_private *priv); void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv); #endif -void mwifiex_do_flr(struct mwifiex_adapter *adapter, bool prepare); +int mwifiex_reinit_sw(struct mwifiex_adapter *adapter); +int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter); #endif /* !_MWIFIEX_MAIN_H_ */ diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 4db07da81d8d..a0d918094889 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -31,8 +31,6 @@ #define PCIE_VERSION "1.0" #define DRV_NAME "Marvell mwifiex PCIe" -static u8 user_rmmod; - static struct mwifiex_if_ops pcie_ops; static const struct of_device_id mwifiex_pcie_of_match_table[] = { @@ -51,6 +49,8 @@ static int mwifiex_pcie_probe_of(struct device *dev) return 0; } +static void mwifiex_pcie_work(struct work_struct *work); + static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, size_t size, int flags) @@ -79,6 +79,42 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, } /* + * This function writes data into PCIE card register. + */ +static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) +{ + struct pcie_service_card *card = adapter->card; + + iowrite32(data, card->pci_mmap1 + reg); + + return 0; +} + +/* This function reads data from PCIE card register. + */ +static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) +{ + struct pcie_service_card *card = adapter->card; + + *data = ioread32(card->pci_mmap1 + reg); + if (*data == 0xffffffff) + return 0xffffffff; + + return 0; +} + +/* This function reads u8 data from PCIE card register. */ +static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter, + int reg, u8 *data) +{ + struct pcie_service_card *card = adapter->card; + + *data = ioread8(card->pci_mmap1 + reg); + + return 0; +} + +/* * This function reads sleep cookie and checks if FW is ready */ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) @@ -219,6 +255,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl; card->pcie.num_mem_types = data->num_mem_types; card->pcie.can_ext_scan = data->can_ext_scan; + INIT_WORK(&card->work, mwifiex_pcie_work); } /* device tree node parsing and platform specific configuration*/ @@ -245,6 +282,9 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) struct pcie_service_card *card; struct mwifiex_adapter *adapter; struct mwifiex_private *priv; + const struct mwifiex_pcie_card_reg *reg; + u32 fw_status; + int ret; card = pci_get_drvdata(pdev); @@ -254,7 +294,15 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) if (!adapter || !adapter->priv_num) return; - if (user_rmmod && !adapter->mfg_mode) { + cancel_work_sync(&card->work); + + reg = card->pcie.reg; + if (reg) + ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); + else + fw_status = -1; + + if (fw_status == FIRMWARE_READY_PCIE && !adapter->mfg_mode) { mwifiex_deauthenticate_all(adapter); priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); @@ -269,7 +317,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) static void mwifiex_pcie_shutdown(struct pci_dev *pdev) { - user_rmmod = 1; mwifiex_pcie_remove(pdev); return; @@ -330,7 +377,7 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) * Cleanup all software without cleaning anything related to * PCIe and HW. */ - mwifiex_do_flr(adapter, prepare); + mwifiex_shutdown_sw(adapter); adapter->surprise_removed = true; } else { /* Kernel stores and restores PCIe function context before and @@ -338,7 +385,7 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) * and firmware including firmware redownload */ adapter->surprise_removed = false; - mwifiex_do_flr(adapter, prepare); + mwifiex_reinit_sw(adapter); } mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); } @@ -369,43 +416,6 @@ static struct pci_driver __refdata mwifiex_pcie = { }; /* - * This function writes data into PCIE card register. - */ -static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) -{ - struct pcie_service_card *card = adapter->card; - - iowrite32(data, card->pci_mmap1 + reg); - - return 0; -} - -/* - * This function reads data from PCIE card register. - */ -static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread32(card->pci_mmap1 + reg); - if (*data == 0xffffffff) - return 0xffffffff; - - return 0; -} - -/* This function reads u8 data from PCIE card register. */ -static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter, - int reg, u8 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread8(card->pci_mmap1 + reg); - - return 0; -} - -/* * This function adds delay loop to ensure FW is awake before proceeding. */ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) @@ -429,16 +439,25 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, struct pcie_service_card *card = adapter->card; u8 *buffer; u32 sleep_cookie, count; + struct sk_buff *cmdrsp = card->cmdrsp_buf; for (count = 0; count < max_delay_loop_cnt; count++) { - buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; - sleep_cookie = *(u32 *)buffer; + pci_dma_sync_single_for_cpu(card->dev, + MWIFIEX_SKB_DMA_ADDR(cmdrsp), + sizeof(sleep_cookie), + PCI_DMA_FROMDEVICE); + buffer = cmdrsp->data; + sleep_cookie = READ_ONCE(*(u32 *)buffer); if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { mwifiex_dbg(adapter, INFO, "sleep cookie found at count %d\n", count); break; } + pci_dma_sync_single_for_device(card->dev, + MWIFIEX_SKB_DMA_ADDR(cmdrsp), + sizeof(sleep_cookie), + PCI_DMA_FROMDEVICE); usleep_range(20, 30); } @@ -450,7 +469,6 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, /* This function wakes up the card by reading fw_status register. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { - u32 fw_status; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -460,10 +478,10 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) if (reg->sleep_cookie) mwifiex_pcie_dev_wakeup_delay(adapter); - /* Reading fw_status register will wakeup device */ - if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) { + /* Accessing fw_status register will wakeup device */ + if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { mwifiex_dbg(adapter, ERROR, - "Reading fw_status register failed\n"); + "Writing fw_status register failed\n"); return -1; } @@ -1681,7 +1699,13 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, CMD, "info: Rx CMD Response\n"); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); + if (adapter->curr_cmd) + mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); + else + pci_dma_sync_single_for_cpu(card->dev, + MWIFIEX_SKB_DMA_ADDR(skb), + MWIFIEX_UPLD_SIZE, + PCI_DMA_FROMDEVICE); /* Unmap the command as a response has been received. */ if (card->cmd_buf) { @@ -1694,10 +1718,13 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) rx_len = le16_to_cpu(pkt_len); skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len); skb_trim(skb, rx_len); - skb_pull(skb, INTF_HEADER_LEN); if (!adapter->curr_cmd) { if (adapter->ps_state == PS_STATE_SLEEP_CFM) { + pci_dma_sync_single_for_device(card->dev, + MWIFIEX_SKB_DMA_ADDR(skb), + MWIFIEX_SLEEP_COOKIE_SIZE, + PCI_DMA_FROMDEVICE); if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, CPU_INTR_SLEEP_CFM_DONE)) { @@ -1707,6 +1734,9 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) } mwifiex_delay_for_sleep_cookie(adapter, MWIFIEX_MAX_DELAY_COUNT); + mwifiex_unmap_pci_memory(adapter, skb, + PCI_DMA_FROMDEVICE); + skb_pull(skb, INTF_HEADER_LEN); while (reg->sleep_cookie && (count++ < 10) && mwifiex_pcie_ok_to_access_hw(adapter)) usleep_range(50, 60); @@ -1724,6 +1754,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) PCI_DMA_FROMDEVICE)) return -1; } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { + skb_pull(skb, INTF_HEADER_LEN); adapter->curr_cmd->resp_skb = skb; adapter->cmd_resp_received = true; /* Take the pointer and set it to CMD node and will @@ -2325,79 +2356,41 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter) } } } - while (pcie_ireg & HOST_INTR_MASK) { - if (pcie_ireg & HOST_INTR_DNLD_DONE) { - pcie_ireg &= ~HOST_INTR_DNLD_DONE; - mwifiex_dbg(adapter, INTR, - "info: TX DNLD Done\n"); - ret = mwifiex_pcie_send_data_complete(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_UPLD_RDY) { - pcie_ireg &= ~HOST_INTR_UPLD_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx DATA\n"); - ret = mwifiex_pcie_process_recv_data(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_EVENT_RDY) { - pcie_ireg &= ~HOST_INTR_EVENT_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx EVENT\n"); - ret = mwifiex_pcie_process_event_ready(adapter); - if (ret) - return ret; - } - - if (pcie_ireg & HOST_INTR_CMD_DONE) { - pcie_ireg &= ~HOST_INTR_CMD_DONE; - if (adapter->cmd_sent) { - mwifiex_dbg(adapter, INTR, - "info: CMD sent Interrupt\n"); - adapter->cmd_sent = false; - } - /* Handle command response */ - ret = mwifiex_pcie_process_cmd_complete(adapter); - if (ret) - return ret; - if (adapter->hs_activated) - return ret; - } - - if (card->msi_enable) { - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - } - - if (mwifiex_pcie_ok_to_access_hw(adapter)) { - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, - &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Read register failed\n"); - return -1; - } - - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { - if (mwifiex_write_reg(adapter, - PCIE_HOST_INT_STATUS, - ~pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - } + if (pcie_ireg & HOST_INTR_DNLD_DONE) { + pcie_ireg &= ~HOST_INTR_DNLD_DONE; + mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n"); + ret = mwifiex_pcie_send_data_complete(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_UPLD_RDY) { + pcie_ireg &= ~HOST_INTR_UPLD_RDY; + mwifiex_dbg(adapter, INTR, "info: Rx DATA\n"); + ret = mwifiex_pcie_process_recv_data(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_EVENT_RDY) { + pcie_ireg &= ~HOST_INTR_EVENT_RDY; + mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n"); + ret = mwifiex_pcie_process_event_ready(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_CMD_DONE) { + pcie_ireg &= ~HOST_INTR_CMD_DONE; + if (adapter->cmd_sent) { + mwifiex_dbg(adapter, INTR, + "info: CMD sent Interrupt\n"); + adapter->cmd_sent = false; } - if (!card->msi_enable) { - spin_lock_irqsave(&adapter->int_lock, flags); - pcie_ireg |= adapter->int_status; - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - } + /* Handle command response */ + ret = mwifiex_pcie_process_cmd_complete(adapter); + if (ret) + return ret; } + mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n", adapter->cmd_sent, adapter->data_sent); @@ -2715,31 +2708,35 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter) { - mwifiex_drv_info_dump(adapter); + int drv_info_size; + void *drv_info; + + drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info); mwifiex_pcie_fw_dump(adapter); - mwifiex_upload_device_dump(adapter); + mwifiex_upload_device_dump(adapter, drv_info, drv_info_size); } -static unsigned long iface_work_flags; -static struct mwifiex_adapter *save_adapter; static void mwifiex_pcie_work(struct work_struct *work) { + struct pcie_service_card *card = + container_of(work, struct pcie_service_card, work); + if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, - &iface_work_flags)) - mwifiex_pcie_device_dump_work(save_adapter); + &card->work_flags)) + mwifiex_pcie_device_dump_work(card->adapter); } -static DECLARE_WORK(pcie_work, mwifiex_pcie_work); /* This function dumps FW information */ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) { - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags)) + struct pcie_service_card *card = adapter->card; + + if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags)) return; - set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); + set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); - schedule_work(&pcie_work); + schedule_work(&card->work); } /* @@ -2752,7 +2749,7 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) * - Allocate command response ring buffer * - Allocate sleep cookie buffer */ -static int mwifiex_pcie_init(struct mwifiex_adapter *adapter) +static int mwifiex_init_pcie(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; int ret; @@ -2861,13 +2858,16 @@ err_enable_dev: * - Command response ring buffer * - Sleep cookie buffer */ -static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) +static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; struct pci_dev *pdev = card->dev; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + int ret; + u32 fw_status; - if (user_rmmod) { + ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); + if (fw_status == FIRMWARE_READY_PCIE) { mwifiex_dbg(adapter, INFO, "Clearing driver ready signature\n"); if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000)) @@ -3058,7 +3058,7 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) * - Allocate event BD ring buffers * - Allocate command response ring buffer * - Allocate sleep cookie buffer - * Part of mwifiex_pcie_init(), not reset the PCIE registers + * Part of mwifiex_init_pcie(), not reset the PCIE registers */ static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter) { @@ -3067,6 +3067,17 @@ static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter) struct pci_dev *pdev = card->dev; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + /* Bluetooth is not on pcie interface. Download Wifi only firmware + * during pcie FLR, so that bluetooth part of firmware which is + * already running doesn't get affected. + */ + strcpy(adapter->fw_name, PCIE8997_DEFAULT_WIFIFW_NAME); + + /* tx_buf_size might be changed to 3584 by firmware during + * data transfer, we should reset it to default size. + */ + adapter->tx_buf_size = card->pcie.tx_buf_size; + card->cmdrsp_buf = NULL; ret = mwifiex_pcie_create_txbd_ring(adapter); if (ret) { @@ -3128,7 +3139,6 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, ERROR, "Failed to write driver not-ready signature\n"); adapter->seq_num = 0; - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; if (reg->sleep_cookie) mwifiex_pcie_delete_sleep_cookie_buf(adapter); @@ -3141,8 +3151,8 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) } static struct mwifiex_if_ops pcie_ops = { - .init_if = mwifiex_pcie_init, - .cleanup_if = mwifiex_pcie_cleanup, + .init_if = mwifiex_init_pcie, + .cleanup_if = mwifiex_cleanup_pcie, .check_fw_status = mwifiex_check_fw_status, .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, @@ -3168,49 +3178,7 @@ static struct mwifiex_if_ops pcie_ops = { .up_dev = mwifiex_pcie_up_dev, }; -/* - * This function initializes the PCIE driver module. - * - * This registers the device with PCIE bus. - */ -static int mwifiex_pcie_init_module(void) -{ - int ret; - - pr_debug("Marvell PCIe Driver\n"); - - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - - ret = pci_register_driver(&mwifiex_pcie); - if (ret) - pr_err("Driver register failed!\n"); - else - pr_debug("info: Driver registered successfully!\n"); - - return ret; -} - -/* - * This function cleans up the PCIE driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from PCIE bus. - */ -static void mwifiex_pcie_cleanup_module(void) -{ - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - - cancel_work_sync(&pcie_work); - pci_unregister_driver(&mwifiex_pcie); -} - -module_init(mwifiex_pcie_init_module); -module_exit(mwifiex_pcie_cleanup_module); +module_pci_driver(mwifiex_pcie); MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index ae3365d1c34e..00e8ee5ad4a8 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -116,6 +116,7 @@ /* FW awake cookie after FW ready */ #define FW_AWAKE_COOKIE (0xAA55AA55) #define MWIFIEX_DEF_SLEEP_COOKIE 0xBEEFBEEF +#define MWIFIEX_SLEEP_COOKIE_SIZE 4 #define MWIFIEX_MAX_DELAY_COUNT 100 struct mwifiex_pcie_card_reg { @@ -386,6 +387,8 @@ struct pcie_service_card { #endif struct mwifiex_msix_context msix_ctx[MWIFIEX_NUM_MSIX_VECTORS]; struct mwifiex_msix_context share_irq_ctx; + struct work_struct work; + unsigned long work_flags; }; static inline int diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 43facba641bf..a4b356d267f9 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -31,23 +31,9 @@ #define SDIO_VERSION "1.0" -/* The mwifiex_sdio_remove() callback function is called when - * user removes this module from kernel space or ejects - * the card from the slot. The driver handles these 2 cases - * differently. - * If the user is removing the module, the few commands (FUNC_SHUTDOWN, - * HS_CANCEL etc.) are sent to the firmware. - * If the card is removed, there is no need to send these command. - * - * The variable 'user_rmmod' is used to distinguish these two - * scenarios. This flag is initialized as FALSE in case the card - * is removed, and will be set to TRUE for module removal when - * module_exit function is called. - */ -static u8 user_rmmod; +static void mwifiex_sdio_work(struct work_struct *work); static struct mwifiex_if_ops sdio_ops; -static unsigned long iface_work_flags; static struct memory_type_mapping generic_mem_type_map[] = { {"DUMP", NULL, 0, 0xDD}, @@ -116,7 +102,6 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) init_completion(&card->fw_done); card->func = func; - card->device_id = id; func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; @@ -136,6 +121,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) card->fw_dump_enh = data->fw_dump_enh; card->can_auto_tdls = data->can_auto_tdls; card->can_ext_scan = data->can_ext_scan; + INIT_WORK(&card->work, mwifiex_sdio_work); } sdio_claim_host(func); @@ -212,6 +198,171 @@ static int mwifiex_sdio_resume(struct device *dev) return 0; } +/* Write data into SDIO card register. Caller claims SDIO device. */ +static int +mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) +{ + int ret = -1; + + sdio_writeb(func, data, reg, &ret); + return ret; +} + +/* This function writes data into SDIO card register. + */ +static int +mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) +{ + struct sdio_mmc_card *card = adapter->card; + int ret; + + sdio_claim_host(card->func); + ret = mwifiex_write_reg_locked(card->func, reg, data); + sdio_release_host(card->func); + + return ret; +} + +/* This function reads data from SDIO card register. + */ +static int +mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data) +{ + struct sdio_mmc_card *card = adapter->card; + int ret = -1; + u8 val; + + sdio_claim_host(card->func); + val = sdio_readb(card->func, reg, &ret); + sdio_release_host(card->func); + + *data = val; + + return ret; +} + +/* This function writes multiple data into SDIO card memory. + * + * This does not work in suspended mode. + */ +static int +mwifiex_write_data_sync(struct mwifiex_adapter *adapter, + u8 *buffer, u32 pkt_len, u32 port) +{ + struct sdio_mmc_card *card = adapter->card; + int ret; + u8 blk_mode = + (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; + u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; + u32 blk_cnt = + (blk_mode == + BLOCK_MODE) ? (pkt_len / + MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; + u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); + + if (adapter->is_suspended) { + mwifiex_dbg(adapter, ERROR, + "%s: not allowed while suspended\n", __func__); + return -1; + } + + sdio_claim_host(card->func); + + ret = sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size); + + sdio_release_host(card->func); + + return ret; +} + +/* This function reads multiple data from SDIO card memory. + */ +static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, + u32 len, u32 port, u8 claim) +{ + struct sdio_mmc_card *card = adapter->card; + int ret; + u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE + : BLOCK_MODE; + u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; + u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) + : len; + u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); + + if (claim) + sdio_claim_host(card->func); + + ret = sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size); + + if (claim) + sdio_release_host(card->func); + + return ret; +} + +/* This function reads the firmware status. + */ +static int +mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) +{ + struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; + u8 fws0, fws1; + + if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0)) + return -1; + + if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1)) + return -1; + + *dat = (u16)((fws1 << 8) | fws0); + return 0; +} + +/* This function checks the firmware status in card. + */ +static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, + u32 poll_num) +{ + int ret = 0; + u16 firmware_stat; + u32 tries; + + for (tries = 0; tries < poll_num; tries++) { + ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); + if (ret) + continue; + if (firmware_stat == FIRMWARE_READY_SDIO) { + ret = 0; + break; + } + + msleep(100); + ret = -1; + } + + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) +{ + int ret = 0; + u8 winner = 0; + struct sdio_mmc_card *card = adapter->card; + + if (mwifiex_read_reg(adapter, card->reg->status_reg_0, &winner)) + return -1; + + if (winner) + adapter->winner = 0; + else + adapter->winner = 1; + + return ret; +} + /* * SDIO remove. * @@ -223,6 +374,8 @@ mwifiex_sdio_remove(struct sdio_func *func) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; struct mwifiex_private *priv; + int ret = 0; + u16 firmware_stat; card = sdio_get_drvdata(func); if (!card) @@ -234,9 +387,12 @@ mwifiex_sdio_remove(struct sdio_func *func) if (!adapter || !adapter->priv_num) return; + cancel_work_sync(&card->work); + mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num); - if (user_rmmod && !adapter->mfg_mode) { + ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); + if (firmware_stat == FIRMWARE_READY_SDIO && !adapter->mfg_mode) { mwifiex_deauthenticate_all(adapter); priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); @@ -364,111 +520,6 @@ static struct sdio_driver mwifiex_sdio = { } }; -/* Write data into SDIO card register. Caller claims SDIO device. */ -static int -mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) -{ - int ret = -1; - sdio_writeb(func, data, reg, &ret); - return ret; -} - -/* - * This function writes data into SDIO card register. - */ -static int -mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - - sdio_claim_host(card->func); - ret = mwifiex_write_reg_locked(card->func, reg, data); - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads data from SDIO card register. - */ -static int -mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - u8 val; - - sdio_claim_host(card->func); - val = sdio_readb(card->func, reg, &ret); - sdio_release_host(card->func); - - *data = val; - - return ret; -} - -/* - * This function writes multiple data into SDIO card memory. - * - * This does not work in suspended mode. - */ -static int -mwifiex_write_data_sync(struct mwifiex_adapter *adapter, - u8 *buffer, u32 pkt_len, u32 port) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u8 blk_mode = - (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = - (blk_mode == - BLOCK_MODE) ? (pkt_len / - MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (adapter->is_suspended) { - mwifiex_dbg(adapter, ERROR, - "%s: not allowed while suspended\n", __func__); - return -1; - } - - sdio_claim_host(card->func); - - ret = sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size); - - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads multiple data from SDIO card memory. - */ -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, - u32 len, u32 port, u8 claim) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE - : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) - : len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (claim) - sdio_claim_host(card->func); - - ret = sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size); - - if (claim) - sdio_release_host(card->func); - - return ret; -} - /* * This function wakes up the card. * @@ -755,27 +806,6 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) } /* - * This function reads the firmware status. - */ -static int -mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - u8 fws0, fws1; - - if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0)) - return -1; - - if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1)) - return -1; - - *dat = (u16) ((fws1 << 8) | fws0); - - return 0; -} - -/* * This function disables the host interrupt. * * The host interrupt mask is read, the disable bit is reset and @@ -1080,51 +1110,6 @@ done: } /* - * This function checks the firmware status in card. - */ -static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, - u32 poll_num) -{ - int ret = 0; - u16 firmware_stat; - u32 tries; - - for (tries = 0; tries < poll_num; tries++) { - ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); - if (ret) - continue; - if (firmware_stat == FIRMWARE_READY_SDIO) { - ret = 0; - break; - } else { - msleep(100); - ret = -1; - } - } - - return ret; -} - -/* This function checks if WLAN is the winner. - */ -static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) -{ - int ret = 0; - u8 winner = 0; - struct sdio_mmc_card *card = adapter->card; - - if (mwifiex_read_reg(adapter, card->reg->status_reg_0, &winner)) - return -1; - - if (winner) - adapter->winner = 0; - else - adapter->winner = 1; - - return ret; -} - -/* * This function decode sdio aggreation pkt. * * Based on the the data block size and pkt_len, @@ -2204,33 +2189,12 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) port, card->mp_data_port_mask); } -static void mwifiex_recreate_adapter(struct sdio_mmc_card *card) +static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) { + struct sdio_mmc_card *card = adapter->card; struct sdio_func *func = card->func; - const struct sdio_device_id *device_id = card->device_id; - - /* TODO mmc_hw_reset does not require destroying and re-probing the - * whole adapter. Hence there was no need to for this rube-goldberg - * design to reload the fw from an external workqueue. If we don't - * destroy the adapter we could reload the fw from - * mwifiex_main_work_queue directly. - * The real difficulty with fw reset is to restore all the user - * settings applied through ioctl. By destroying and recreating the - * adapter, we take the easy way out, since we rely on user space to - * restore them. We assume that user space will treat the new - * incarnation of the adapter(interfaces) as if they had been just - * discovered and initializes them from scratch. - */ - mwifiex_sdio_remove(func); - - /* - * Normally, we would let the driver core take care of releasing these. - * But we're not letting the driver core handle this one. See above - * TODO. - */ - sdio_set_drvdata(func, NULL); - devm_kfree(&func->dev, card); + mwifiex_shutdown_sw(adapter); /* power cycle the adapter */ sdio_claim_host(func); @@ -2240,24 +2204,10 @@ static void mwifiex_recreate_adapter(struct sdio_mmc_card *card) /* Previous save_adapter won't be valid after this. We will cancel * pending work requests. */ - clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); - clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); - - mwifiex_sdio_probe(func, device_id); -} - -static struct mwifiex_adapter *save_adapter; -static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; + clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - /* TODO card pointer is unprotected. If the adapter is removed - * physically, sdio core might trigger mwifiex_sdio_remove, before this - * workqueue is run, which will destroy the adapter struct. When this - * workqueue eventually exceutes it will dereference an invalid adapter - * pointer - */ - mwifiex_recreate_adapter(card); + mwifiex_reinit_sw(adapter); } /* This function read/write firmware */ @@ -2548,47 +2498,53 @@ done: static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; + int drv_info_size; + void *drv_info; - mwifiex_drv_info_dump(adapter); + drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info); if (card->fw_dump_enh) mwifiex_sdio_generic_fw_dump(adapter); else mwifiex_sdio_fw_dump(adapter); - mwifiex_upload_device_dump(adapter); + mwifiex_upload_device_dump(adapter, drv_info, drv_info_size); } static void mwifiex_sdio_work(struct work_struct *work) { + struct sdio_mmc_card *card = + container_of(work, struct sdio_mmc_card, work); + if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, - &iface_work_flags)) - mwifiex_sdio_device_dump_work(save_adapter); + &card->work_flags)) + mwifiex_sdio_device_dump_work(card->adapter); if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, - &iface_work_flags)) - mwifiex_sdio_card_reset_work(save_adapter); + &card->work_flags)) + mwifiex_sdio_card_reset_work(card->adapter); } -static DECLARE_WORK(sdio_work, mwifiex_sdio_work); /* This function resets the card */ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) { - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags)) + struct sdio_mmc_card *card = adapter->card; + + if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags)) return; - set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); + set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - schedule_work(&sdio_work); + schedule_work(&card->work); } /* This function dumps FW information */ static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter) { - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags)) + struct sdio_mmc_card *card = adapter->card; + + if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags)) return; - set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); - schedule_work(&sdio_work); + set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + schedule_work(&card->work); } /* Function to dump SDIO function registers and SDIO scratch registers in case @@ -2684,6 +2640,33 @@ mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf) return p - drv_buf; } +/* sdio device/function initialization, code is extracted + * from init_if handler and register_dev handler. + */ +static void mwifiex_sdio_up_dev(struct mwifiex_adapter *adapter) +{ + struct sdio_mmc_card *card = adapter->card; + u8 sdio_ireg; + + sdio_claim_host(card->func); + sdio_enable_func(card->func); + sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); + sdio_release_host(card->func); + + /* tx_buf_size might be changed to 3584 by firmware during + * data transfer, we will reset to default size. + */ + adapter->tx_buf_size = card->tx_buf_size; + + /* Read the host_int_status_reg for ACK the first interrupt got + * from the bootloader. If we don't do this we get a interrupt + * as soon as we register the irq. + */ + mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); + + mwifiex_init_sdio_ioport(adapter); +} + static struct mwifiex_if_ops sdio_ops = { .init_if = mwifiex_init_sdio, .cleanup_if = mwifiex_cleanup_sdio, @@ -2709,43 +2692,10 @@ static struct mwifiex_if_ops sdio_ops = { .reg_dump = mwifiex_sdio_reg_dump, .device_dump = mwifiex_sdio_device_dump, .deaggr_pkt = mwifiex_deaggr_sdio_pkt, + .up_dev = mwifiex_sdio_up_dev, }; -/* - * This function initializes the SDIO driver. - * - * This registers the device with SDIO bus. - */ -static int -mwifiex_sdio_init_module(void) -{ - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - - return sdio_register_driver(&mwifiex_sdio); -} - -/* - * This function cleans up the SDIO driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from SDIO bus. - */ -static void -mwifiex_sdio_cleanup_module(void) -{ - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - cancel_work_sync(&sdio_work); - - sdio_unregister_driver(&mwifiex_sdio); -} - -module_init(mwifiex_sdio_init_module); -module_exit(mwifiex_sdio_cleanup_module); +module_driver(mwifiex_sdio, sdio_register_driver, sdio_unregister_driver); MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index cdbf3a3ac7f9..dccf7fd1aef3 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -268,8 +268,8 @@ struct sdio_mmc_card { struct mwifiex_sdio_mpa_tx mpa_tx; struct mwifiex_sdio_mpa_rx mpa_rx; - /* needed for card reset */ - const struct sdio_device_id *device_id; + struct work_struct work; + unsigned long work_flags; }; struct mwifiex_sdio_device { diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 9df0c4dc06ed..96503d3d053f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -1009,6 +1009,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->event_skb->len - sizeof(eventcause)); break; + /* Debugging event; not used, but let's not print an ERROR for it. */ + case EVENT_UNKNOWN_DEBUG: + mwifiex_dbg(adapter, EVENT, "event: debug\n"); + break; default: mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index c563160b3b6b..9cf3334adf4d 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -22,7 +22,6 @@ #define USB_VERSION "1.0" -static u8 user_rmmod; static struct mwifiex_if_ops usb_ops; static struct usb_device_id mwifiex_usb_table[] = { @@ -618,7 +617,7 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf) if (!adapter || !adapter->priv_num) return; - if (user_rmmod && !adapter->mfg_mode) { + if (card->udev->state != USB_STATE_NOTATTACHED && !adapter->mfg_mode) { mwifiex_deauthenticate_all(adapter); mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, @@ -1201,43 +1200,7 @@ static struct mwifiex_if_ops usb_ops = { .is_port_ready = mwifiex_usb_is_port_ready, }; -/* This function initializes the USB driver module. - * - * This registers the device with USB bus. - */ -static int mwifiex_usb_init_module(void) -{ - int ret; - - pr_debug("Marvell USB8797 Driver\n"); - - ret = usb_register(&mwifiex_usb_driver); - if (ret) - pr_err("Driver register failed!\n"); - else - pr_debug("info: Driver registered successfully!\n"); - - return ret; -} - -/* This function cleans up the USB driver. - * - * The following major steps are followed in .disconnect for cleanup: - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from USB bus. - */ -static void mwifiex_usb_cleanup_module(void) -{ - /* set the flag as user is removing this module */ - user_rmmod = 1; - - usb_deregister(&mwifiex_usb_driver); -} - -module_init(mwifiex_usb_init_module); -module_exit(mwifiex_usb_cleanup_module); +module_usb_driver(mwifiex_usb_driver); MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 18fbb96a46e9..b1ab8da121dd 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -146,21 +146,6 @@ int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter) } /* - * Firmware shutdown complete callback handler. - * - * This function sets the hardware status to not ready and wakes up - * the function waiting on the init wait queue for the firmware - * shutdown to complete. - */ -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) -{ - adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; - adapter->init_wait_q_woken = true; - wake_up_interruptible(&adapter->init_wait_q); - return 0; -} - -/* * This function sends init/shutdown command * to firmware. */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h index ec622a08a486..256496bfbafb 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h @@ -72,6 +72,7 @@ #define RF5592 0x000f #define RF3070 0x3070 #define RF3290 0x3290 +#define RF5350 0x5350 #define RF5360 0x5360 #define RF5362 0x5362 #define RF5370 0x5370 @@ -2286,6 +2287,8 @@ struct mac_iveiv_entry { #define RFCSR30_RX_H20M FIELD8(0x04) #define RFCSR30_RX_VCM FIELD8(0x18) #define RFCSR30_RF_CALIBRATION FIELD8(0x80) +#define RF3322_RFCSR30_TX_H20M FIELD8(0x01) +#define RF3322_RFCSR30_RX_H20M FIELD8(0x02) /* * RFCSR 31: @@ -2301,6 +2304,12 @@ struct mac_iveiv_entry { #define RFCSR36_RF_BS FIELD8(0x80) /* + * RFCSR 34: + */ +#define RFCSR34_TX0_EXT_PA FIELD8(0x04) +#define RFCSR34_TX1_EXT_PA FIELD8(0x08) + +/* * RFCSR 38: */ #define RFCSR38_RX_LO1_EN FIELD8(0x20) @@ -2312,6 +2321,18 @@ struct mac_iveiv_entry { #define RFCSR39_RX_LO2_EN FIELD8(0x80) /* + * RFCSR 41: + */ +#define RFCSR41_BIT1 FIELD8(0x01) +#define RFCSR41_BIT4 FIELD8(0x08) + +/* + * RFCSR 42: + */ +#define RFCSR42_BIT1 FIELD8(0x01) +#define RFCSR42_BIT4 FIELD8(0x08) + +/* * RFCSR 49: */ #define RFCSR49_TX FIELD8(0x3f) @@ -2324,6 +2345,8 @@ struct mac_iveiv_entry { * RFCSR 50: */ #define RFCSR50_TX FIELD8(0x3f) +#define RFCSR50_TX0_EXT_PA FIELD8(0x02) +#define RFCSR50_TX1_EXT_PA FIELD8(0x10) #define RFCSR50_EP FIELD8(0xc0) /* bits for RT3593 */ #define RFCSR50_TX_LO1_EN FIELD8(0x20) @@ -2471,6 +2494,8 @@ enum rt2800_eeprom_word { * INTERNAL_TX_ALC: 0: disable, 1: enable * BT_COEXIST: 0: disable, 1: enable * DAC_TEST: 0: disable, 1: enable + * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352) + * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352) */ #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) @@ -2487,6 +2512,8 @@ enum rt2800_eeprom_word { #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) +#define EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352 FIELD16(0x4000) +#define EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352 FIELD16(0x8000) /* * EEPROM frequency diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 5436cdb07937..572cdea4ca25 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -373,9 +373,6 @@ static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) int i, count; rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); - if (rt2x00_get_field32(reg, WLAN_EN)) - return 0; - rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); rt2x00_set_field32(®, WLAN_CLK_EN, 0); @@ -967,8 +964,6 @@ static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev) bcn_num++; } - WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing); - rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg); rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32)); @@ -1937,6 +1932,11 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, rt2x00dev->lna_gain = lna_gain; } +static inline bool rt2800_clk_is_20mhz(struct rt2x00_dev *rt2x00dev) +{ + return clk_get_rate(rt2x00dev->clk) == 20000000; +} + #define FREQ_OFFSET_BOUND 0x5f static void rt2800_freq_cal_mode1(struct rt2x00_dev *rt2x00dev) @@ -2760,6 +2760,13 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 59, r59_non_bt[idx]); + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + static const char r59_non_bt[] = {0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, + 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06}; + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); } } } @@ -3197,6 +3204,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); break; case RF3070: + case RF5350: case RF5360: case RF5362: case RF5370: @@ -3215,6 +3223,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, if (rt2x00_rf(rt2x00dev, RF3070) || rt2x00_rf(rt2x00dev, RF3290) || rt2x00_rf(rt2x00dev, RF3322) || + rt2x00_rf(rt2x00dev, RF5350) || rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5362) || rt2x00_rf(rt2x00dev, RF5370) || @@ -3222,8 +3231,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_rf(rt2x00dev, RF5390) || rt2x00_rf(rt2x00dev, RF5392)) { rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); - rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); + if (rt2x00_rf(rt2x00dev, RF3322)) { + rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M, + conf_is_ht40(conf)); + rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_RX_H20M, + conf_is_ht40(conf)); + } else { + rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, + conf_is_ht40(conf)); + rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, + conf_is_ht40(conf)); + } rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); @@ -3234,11 +3252,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, /* * Change BBP settings */ + if (rt2x00_rt(rt2x00dev, RT3352)) { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 27, 0x0); rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 27, 0x20); rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 86, 0x38); + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } else if (rt2x00_rt(rt2x00dev, RT3593)) { if (rf->channel > 14) { /* Disable CCK Packet detection on 5GHz */ @@ -3456,7 +3481,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, /* * Clear update flag */ - if (rt2x00_rt(rt2x00dev, RT3352)) { + if (rt2x00_rt(rt2x00dev, RT3352) || + rt2x00_rt(rt2x00dev, RT5350)) { rt2800_bbp_read(rt2x00dev, 49, &bbp); rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); rt2800_bbp_write(rt2x00dev, 49, bbp); @@ -4337,6 +4363,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) case RF3053: case RF3070: case RF3290: + case RF5350: case RF5360: case RF5362: case RF5370: @@ -4719,6 +4746,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); } else { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -4743,15 +4772,16 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || - rt2x00_rt(rt2x00dev, RT2883) || - rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) { + if (rt2x00_is_usb(rt2x00dev)) { + drv_data->max_psdu = 3; + } else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || + rt2x00_rt(rt2x00dev, RT2883) || + rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) { drv_data->max_psdu = 2; - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); } else { drv_data->max_psdu = 1; - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); } + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, drv_data->max_psdu); rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 10); rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 10); rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); @@ -4769,8 +4799,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); - rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, 15); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, 31); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, 2); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, 2); rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); @@ -4902,10 +4932,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); - rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7); rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, IEEE80211_MAX_RTS_THRESHOLD); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 1); rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); @@ -5363,9 +5393,13 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); - rt2800_bbp_write(rt2x00dev, 83, 0x6a); - - rt2800_bbp_write(rt2x00dev, 84, 0x99); + if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_bbp_write(rt2x00dev, 83, 0x7a); + rt2800_bbp_write(rt2x00dev, 84, 0x9a); + } else { + rt2800_bbp_write(rt2x00dev, 83, 0x6a); + rt2800_bbp_write(rt2x00dev, 84, 0x99); + } rt2800_bbp_write(rt2x00dev, 86, 0x38); @@ -5379,9 +5413,13 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 104, 0x92); - rt2800_bbp_write(rt2x00dev, 105, 0x34); - - rt2800_bbp_write(rt2x00dev, 106, 0x05); + if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_bbp_write(rt2x00dev, 105, 0x3c); + rt2800_bbp_write(rt2x00dev, 106, 0x03); + } else { + rt2800_bbp_write(rt2x00dev, 105, 0x34); + rt2800_bbp_write(rt2x00dev, 106, 0x05); + } rt2800_bbp_write(rt2x00dev, 120, 0x50); @@ -5406,6 +5444,16 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 143, 0xa2); rt2800_bbp_write(rt2x00dev, 148, 0xc8); + + if (rt2x00_rt(rt2x00dev, RT5350)) { + /* Antenna Software OFDM */ + rt2800_bbp_write(rt2x00dev, 150, 0x40); + /* Antenna Software CCK */ + rt2800_bbp_write(rt2x00dev, 151, 0x30); + rt2800_bbp_write(rt2x00dev, 152, 0xa3); + /* Clear previously selected antenna */ + rt2800_bbp_write(rt2x00dev, 154, 0); + } } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -5706,6 +5754,7 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_init_bbp_3290(rt2x00dev); break; case RT3352: + case RT5350: rt2800_init_bbp_3352(rt2x00dev); break; case RT3390: @@ -6179,6 +6228,12 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev) static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) { + int tx0_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX0, + &rt2x00dev->cap_flags); + int tx1_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX1, + &rt2x00dev->cap_flags); + u8 rfcsr; + rt2800_rf_init_calibration(rt2x00dev, 30); rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); @@ -6214,15 +6269,30 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 31, 0x80); rt2800_rfcsr_write(rt2x00dev, 32, 0x80); rt2800_rfcsr_write(rt2x00dev, 33, 0x00); - rt2800_rfcsr_write(rt2x00dev, 34, 0x01); + rfcsr = 0x01; + if (!tx0_int_pa) + rt2x00_set_field8(&rfcsr, RFCSR34_TX0_EXT_PA, 1); + if (!tx1_int_pa) + rt2x00_set_field8(&rfcsr, RFCSR34_TX1_EXT_PA, 1); + rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); rt2800_rfcsr_write(rt2x00dev, 35, 0x03); rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); rt2800_rfcsr_write(rt2x00dev, 40, 0x33); - rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); - rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); + rfcsr = 0x52; + if (tx0_int_pa) { + rt2x00_set_field8(&rfcsr, RFCSR41_BIT1, 1); + rt2x00_set_field8(&rfcsr, RFCSR41_BIT4, 1); + } + rt2800_rfcsr_write(rt2x00dev, 41, rfcsr); + rfcsr = 0x52; + if (tx1_int_pa) { + rt2x00_set_field8(&rfcsr, RFCSR42_BIT1, 1); + rt2x00_set_field8(&rfcsr, RFCSR42_BIT4, 1); + } + rt2800_rfcsr_write(rt2x00dev, 42, rfcsr); rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); @@ -6230,15 +6300,20 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); rt2800_rfcsr_write(rt2x00dev, 48, 0x14); rt2800_rfcsr_write(rt2x00dev, 49, 0x00); - rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); - rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); - rt2800_rfcsr_write(rt2x00dev, 52, 0x00); - rt2800_rfcsr_write(rt2x00dev, 53, 0x52); - rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); - rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); - rt2800_rfcsr_write(rt2x00dev, 56, 0x00); - rt2800_rfcsr_write(rt2x00dev, 57, 0x52); - rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); + rfcsr = 0x2d; + if (!tx0_int_pa) + rt2x00_set_field8(&rfcsr, RFCSR50_TX0_EXT_PA, 1); + if (!tx1_int_pa) + rt2x00_set_field8(&rfcsr, RFCSR50_TX1_EXT_PA, 1); + rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + rt2800_rfcsr_write(rt2x00dev, 51, (tx0_int_pa ? 0x7f : 0x52)); + rt2800_rfcsr_write(rt2x00dev, 52, (tx0_int_pa ? 0x00 : 0xc0)); + rt2800_rfcsr_write(rt2x00dev, 53, (tx0_int_pa ? 0x52 : 0xd2)); + rt2800_rfcsr_write(rt2x00dev, 54, (tx0_int_pa ? 0x1b : 0xc0)); + rt2800_rfcsr_write(rt2x00dev, 55, (tx1_int_pa ? 0x7f : 0x52)); + rt2800_rfcsr_write(rt2x00dev, 56, (tx1_int_pa ? 0x00 : 0xc0)); + rt2800_rfcsr_write(rt2x00dev, 57, (tx0_int_pa ? 0x52 : 0x49)); + rt2800_rfcsr_write(rt2x00dev, 58, (tx1_int_pa ? 0x1b : 0xc0)); rt2800_rfcsr_write(rt2x00dev, 59, 0x00); rt2800_rfcsr_write(rt2x00dev, 60, 0x00); rt2800_rfcsr_write(rt2x00dev, 61, 0x00); @@ -6490,6 +6565,76 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) /* TODO: enable stream mode support */ } +static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev) +{ + rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); + rt2800_rfcsr_write(rt2x00dev, 1, 0x23); + rt2800_rfcsr_write(rt2x00dev, 2, 0x50); + rt2800_rfcsr_write(rt2x00dev, 3, 0x08); + rt2800_rfcsr_write(rt2x00dev, 4, 0x49); + rt2800_rfcsr_write(rt2x00dev, 5, 0x10); + rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); + rt2800_rfcsr_write(rt2x00dev, 7, 0x00); + rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); + rt2800_rfcsr_write(rt2x00dev, 9, 0x02); + rt2800_rfcsr_write(rt2x00dev, 10, 0x53); + rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); + rt2800_rfcsr_write(rt2x00dev, 12, 0x46); + if (rt2800_clk_is_20mhz(rt2x00dev)) + rt2800_rfcsr_write(rt2x00dev, 13, 0x1f); + else + rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); + rt2800_rfcsr_write(rt2x00dev, 14, 0x00); + rt2800_rfcsr_write(rt2x00dev, 15, 0x00); + rt2800_rfcsr_write(rt2x00dev, 16, 0xc0); + rt2800_rfcsr_write(rt2x00dev, 18, 0x03); + rt2800_rfcsr_write(rt2x00dev, 19, 0x00); + rt2800_rfcsr_write(rt2x00dev, 20, 0x00); + rt2800_rfcsr_write(rt2x00dev, 21, 0x00); + rt2800_rfcsr_write(rt2x00dev, 22, 0x20); + rt2800_rfcsr_write(rt2x00dev, 23, 0x00); + rt2800_rfcsr_write(rt2x00dev, 24, 0x00); + rt2800_rfcsr_write(rt2x00dev, 25, 0x80); + rt2800_rfcsr_write(rt2x00dev, 26, 0x00); + rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + rt2800_rfcsr_write(rt2x00dev, 28, 0x00); + rt2800_rfcsr_write(rt2x00dev, 29, 0xd0); + rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); + rt2800_rfcsr_write(rt2x00dev, 34, 0x07); + rt2800_rfcsr_write(rt2x00dev, 35, 0x12); + rt2800_rfcsr_write(rt2x00dev, 36, 0x00); + rt2800_rfcsr_write(rt2x00dev, 37, 0x08); + rt2800_rfcsr_write(rt2x00dev, 38, 0x85); + rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); + rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); + rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); + rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); + rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); + rt2800_rfcsr_write(rt2x00dev, 44, 0x0c); + rt2800_rfcsr_write(rt2x00dev, 45, 0xa6); + rt2800_rfcsr_write(rt2x00dev, 46, 0x73); + rt2800_rfcsr_write(rt2x00dev, 47, 0x00); + rt2800_rfcsr_write(rt2x00dev, 48, 0x10); + rt2800_rfcsr_write(rt2x00dev, 49, 0x80); + rt2800_rfcsr_write(rt2x00dev, 50, 0x00); + rt2800_rfcsr_write(rt2x00dev, 51, 0x00); + rt2800_rfcsr_write(rt2x00dev, 52, 0x38); + rt2800_rfcsr_write(rt2x00dev, 53, 0x00); + rt2800_rfcsr_write(rt2x00dev, 54, 0x38); + rt2800_rfcsr_write(rt2x00dev, 55, 0x43); + rt2800_rfcsr_write(rt2x00dev, 56, 0x82); + rt2800_rfcsr_write(rt2x00dev, 57, 0x00); + rt2800_rfcsr_write(rt2x00dev, 58, 0x39); + rt2800_rfcsr_write(rt2x00dev, 59, 0x0b); + rt2800_rfcsr_write(rt2x00dev, 60, 0x45); + rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); + rt2800_rfcsr_write(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write(rt2x00dev, 63, 0x00); +} + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) { rt2800_rf_init_calibration(rt2x00dev, 2); @@ -6727,6 +6872,9 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) case RT3593: rt2800_init_rfcsr_3593(rt2x00dev); break; + case RT5350: + rt2800_init_rfcsr_5350(rt2x00dev); + break; case RT5390: rt2800_init_rfcsr_5390(rt2x00dev); break; @@ -7104,6 +7252,10 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + else if (rt2x00_rt(rt2x00dev, RT3352)) + rf = RF3322; + else if (rt2x00_rt(rt2x00dev, RT5350)) + rf = RF5350; else rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); @@ -7122,6 +7274,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF3290: case RF3320: case RF3322: + case RF5350: case RF5360: case RF5362: case RF5370: @@ -7193,7 +7346,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Detect if this device has Bluetooth co-existence. */ - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) + if (!rt2x00_rt(rt2x00dev, RT3352) && + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); /* @@ -7222,6 +7376,22 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) EIRP_MAX_TX_POWER_LIMIT) __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + /* + * Detect if device uses internal or external PA + */ + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + + if (rt2x00_rt(rt2x00dev, RT3352)) { + if (!rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352)) + __set_bit(CAPABILITY_INTERNAL_PA_TX0, + &rt2x00dev->cap_flags); + if (!rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352)) + __set_bit(CAPABILITY_INTERNAL_PA_TX1, + &rt2x00dev->cap_flags); + } + return 0; } @@ -7366,6 +7536,27 @@ static const struct rf_channel rf_vals_3x[] = { {173, 0x61, 0, 9}, }; +/* + * RF value list for rt3xxx with Xtal20MHz + * Supports: 2.4 GHz (all) (RF3322) + */ +static const struct rf_channel rf_vals_3x_xtal20[] = { + {1, 0xE2, 2, 0x14}, + {2, 0xE3, 2, 0x14}, + {3, 0xE4, 2, 0x14}, + {4, 0xE5, 2, 0x14}, + {5, 0xE6, 2, 0x14}, + {6, 0xE7, 2, 0x14}, + {7, 0xE8, 2, 0x14}, + {8, 0xE9, 2, 0x14}, + {9, 0xEA, 2, 0x14}, + {10, 0xEB, 2, 0x14}, + {11, 0xEC, 2, 0x14}, + {12, 0xED, 2, 0x14}, + {13, 0xEE, 2, 0x14}, + {14, 0xF0, 2, 0x18}, +}; + static const struct rf_channel rf_vals_5592_xtal20[] = { /* Channel, N, K, mod, R */ {1, 482, 4, 10, 3}, @@ -7514,6 +7705,13 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; /* + * Change default retry settings to values corresponding more closely + * to rate[0].count setting of minstrel rate control algorithm. + */ + rt2x00dev->hw->wiphy->retry_short = 2; + rt2x00dev->hw->wiphy->retry_long = 2; + + /* * Initialize all hw fields. */ ieee80211_hw_set(rt2x00dev->hw, REPORTS_TX_ACK_STATUS); @@ -7580,6 +7778,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF3290: case RF3320: case RF3322: + case RF5350: case RF5360: case RF5362: case RF5370: @@ -7587,7 +7786,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF5390: case RF5392: spec->num_channels = 14; - spec->channels = rf_vals_3x; + if (rt2800_clk_is_20mhz(rt2x00dev)) + spec->channels = rf_vals_3x_xtal20; + else + spec->channels = rf_vals_3x; break; case RF3052: @@ -7713,6 +7915,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF3053: case RF3070: case RF3290: + case RF5350: case RF5360: case RF5362: case RF5370: @@ -7753,6 +7956,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) case RT3390: case RT3572: case RT3593: + case RT5350: case RT5390: case RT5392: case RT5592: diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index f38c44061b5b..205a7b8ac8a7 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -123,7 +123,7 @@ static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry) if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) return false; - tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); + tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500)); if (unlikely(tout)) rt2x00_dbg(entry->queue->rt2x00dev, "TX status timeout for entry %d in queue %d\n", @@ -436,47 +436,6 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, } /* - * Watchdog handlers - */ -static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); - if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { - rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n"); - - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012); - - for (i = 0; i < 10; i++) { - udelay(10); - if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) - break; - } - - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); - } - - rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); - if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { - rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n"); - - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a); - - for (i = 0; i < 10; i++) { - udelay(10); - if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) - break; - } - - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); - } - - rt2x00usb_watchdog(rt2x00dev); -} - -/* * TX descriptor initialization */ static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) @@ -643,10 +602,9 @@ static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev) !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; - if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) || + rt2800usb_entry_txstatus_timeout(entry)) rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); - else if (rt2800usb_entry_txstatus_timeout(entry)) - rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); else break; } @@ -877,7 +835,6 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_tuner = rt2800_link_tuner, .gain_calibration = rt2800_gain_calibration, .vco_calibration = rt2800_vco_calibration, - .watchdog = rt2800usb_watchdog, .start_queue = rt2800usb_start_queue, .kick_queue = rt2x00usb_kick_queue, .stop_queue = rt2800usb_stop_queue, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 034a07273038..ea299c4e7ada 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -39,6 +39,7 @@ #include <linux/hrtimer.h> #include <linux/average.h> #include <linux/usb.h> +#include <linux/clk.h> #include <net/mac80211.h> @@ -169,6 +170,7 @@ struct rt2x00_chip { #define RT3572 0x3572 #define RT3593 0x3593 #define RT3883 0x3883 /* WSOC */ +#define RT5350 0x5350 /* WSOC 2.4GHz */ #define RT5390 0x5390 /* 2.4GHz */ #define RT5392 0x5392 /* 2.4GHz */ #define RT5592 0x5592 @@ -716,6 +718,8 @@ enum rt2x00_capability_flags { CAPABILITY_DOUBLE_ANTENNA, CAPABILITY_BT_COEXIST, CAPABILITY_VCO_RECALIBRATION, + CAPABILITY_INTERNAL_PA_TX0, + CAPABILITY_INTERNAL_PA_TX1, }; /* @@ -1009,6 +1013,9 @@ struct rt2x00_dev { unsigned int extra_tx_headroom; struct usb_anchor *anchor; + + /* Clock for System On Chip devices. */ + struct clk *clk; }; struct rt2x00_bar_list_entry { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c index 6a1f508d472f..350507458ddc 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c @@ -249,6 +249,22 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, */ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags); + if (conf->flags & IEEE80211_CONF_PS) + set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + else + clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + + if (conf->flags & IEEE80211_CONF_MONITOR) + set_bit(CONFIG_MONITORING, &rt2x00dev->flags); + else + clear_bit(CONFIG_MONITORING, &rt2x00dev->flags); + + rt2x00dev->curr_band = conf->chandef.chan->band; + rt2x00dev->curr_freq = conf->chandef.chan->center_freq; + rt2x00dev->tx_power = conf->power_level; + rt2x00dev->short_retry = conf->short_frame_max_tx_count; + rt2x00dev->long_retry = conf->long_frame_max_tx_count; + /* * Some configuration changes affect the link quality * which means we need to reset the link tuner. @@ -271,20 +287,4 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, &rt2x00dev->autowakeup_work, autowake_timeout - 15); } - - if (conf->flags & IEEE80211_CONF_PS) - set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); - else - clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); - - if (conf->flags & IEEE80211_CONF_MONITOR) - set_bit(CONFIG_MONITORING, &rt2x00dev->flags); - else - clear_bit(CONFIG_MONITORING, &rt2x00dev->flags); - - rt2x00dev->curr_band = conf->chandef.chan->band; - rt2x00dev->curr_freq = conf->chandef.chan->center_freq; - rt2x00dev->tx_power = conf->power_level; - rt2x00dev->short_retry = conf->short_frame_max_tx_count; - rt2x00dev->long_retry = conf->long_frame_max_tx_count; } diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c index 3cc1384ed2fc..ecc96312a370 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c @@ -743,7 +743,8 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return; tx_queue_for_each(rt2x00dev, queue) - rt2x00queue_flush_queue(queue, drop); + if (!rt2x00queue_empty(queue)) + rt2x00queue_flush_queue(queue, drop); } EXPORT_SYMBOL_GPL(rt2x00mac_flush); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c index f0178fd4fe5f..da38d254c26f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c @@ -101,7 +101,7 @@ void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop) unsigned int i; for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) - msleep(10); + msleep(50); } EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c index 69a0cdadb07f..29250f79c4a4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c @@ -93,6 +93,10 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops) rt2x00dev->irq = platform_get_irq(pdev, 0); rt2x00dev->name = pdev->dev.driver->name; + rt2x00dev->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(rt2x00dev->clk)) + rt2x00dev->clk = NULL; + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); retval = rt2x00soc_alloc_reg(rt2x00dev); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c index 6005e14213ca..838ca58d2dd6 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c @@ -517,7 +517,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) * Wait for a little while to give the driver * the oppurtunity to recover itself. */ - msleep(10); + msleep(50); } } EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index df551b2b56eb..95e3993d8a33 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * 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_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c index f9e2050812ab..a41a29612582 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver - 8188c/8188r/8192c specific subdriver * - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index a1178c5d6ad8..80fee699f58a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver - 8192e specific subdriver * - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c index aef373028155..174631132b96 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver - 8723a specific subdriver * - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 02b8ddd98a95..c4b86a84a721 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver - 8723b specific subdriver * - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 3a86675020a2..e544dd1d618c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -1,7 +1,7 @@ /* * RTL8XXXU mac80211 USB driver * - * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * Portions, notably calibration code: * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. @@ -48,7 +48,7 @@ static bool rtl8xxxu_dma_aggregation; static int rtl8xxxu_dma_agg_timeout = -1; static int rtl8xxxu_dma_agg_pages = -1; -MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>"); +MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>"); MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin"); @@ -6000,6 +6000,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, case 0x8176: case 0x8178: case 0x817f: + case 0x818b: untested = 0; break; } @@ -6196,6 +6197,12 @@ static struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8723au_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818b, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192eu_fops}, +/* TP-Link TL-WN822N v4 */ +{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0108, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192eu_fops}, +/* D-Link DWA-131 rev E1, tested by David Patiño */ +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3319, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192eu_fops}, /* Tested by Myckel Habets */ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0109, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192eu_fops}, @@ -6347,6 +6354,13 @@ static struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, +/* found in rtl8192eu vendor driver */ +{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0107, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192eu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab33, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192eu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818c, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192eu_fops}, #endif { } }; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 315ccfb2dff5..3d3e2e1ada6f 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 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com> + * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com> * * 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/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 13325e15929e..01cf0a9aa31b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -2083,65 +2083,6 @@ void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) } EXPORT_SYMBOL_GPL(rtl_recognize_peer); -/********************************************************* - * - * sysfs functions - * - *********************************************************/ -static ssize_t rtl_show_debug_level(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ieee80211_hw *hw = dev_get_drvdata(d); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - return sprintf(buf, "0x%08X\n", rtlpriv->dbg.global_debuglevel); -} - -static ssize_t rtl_store_debug_level(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ieee80211_hw *hw = dev_get_drvdata(d); - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned long val; - int ret; - - ret = kstrtoul(buf, 0, &val); - if (ret) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "%s is not in hex or decimal form.\n", buf); - } else { - rtlpriv->dbg.global_debuglevel = val; - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "debuglevel:%x\n", - rtlpriv->dbg.global_debuglevel); - } - - return strnlen(buf, count); -} - -static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, - rtl_show_debug_level, rtl_store_debug_level); - -static struct attribute *rtl_sysfs_entries[] = { - - &dev_attr_debug_level.attr, - - NULL -}; - -/* - * "name" is folder name witch will be - * put in device directory like : - * sys/devices/pci0000:00/0000:00:1c.4/ - * 0000:06:00.0/rtl_sysfs - */ -struct attribute_group rtl_attribute_group = { - .name = "rtlsysfs", - .attrs = rtl_sysfs_entries, -}; -EXPORT_SYMBOL_GPL(rtl_attribute_group); - MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index 74233d601a90..6c770aecebe7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -148,7 +148,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(u8 tid); -extern struct attribute_group rtl_attribute_group; void rtl_easy_concurrent_retrytimer_callback(unsigned long data); extern struct rtl_global_var rtl_global_var; void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index 33905bbacad2..7ecac6116d5d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.c +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c @@ -26,35 +26,32 @@ #include <linux/moduleparam.h> -void rtl_dbgp_flag_init(struct ieee80211_hw *hw) +#ifdef CONFIG_RTLWIFI_DEBUG +void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level, + const char *fmt, ...) { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 i; + if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) && + (level <= rtlpriv->cfg->mod_params->debug_level))) { + struct va_format vaf; + va_list args; - rtlpriv->dbg.global_debugcomponents = - COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND | - COMP_MLME | COMP_SCAN | COMP_INTR | COMP_LED | COMP_SEC | - COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | - COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | - COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | - COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN | - COMP_EASY_CONCURRENT | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | - COMP_REGD | COMP_CHAN | COMP_BT_COEXIST; + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; - for (i = 0; i < DBGP_TYPE_MAX; i++) - rtlpriv->dbg.dbgp_type[i] = 0; + pr_info(":<%lx> %pV", in_interrupt(), &vaf); - /*Init Debug flag enable condition */ + va_end(args); + } } -EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init); +EXPORT_SYMBOL_GPL(_rtl_dbg_trace); -#ifdef CONFIG_RTLWIFI_DEBUG -void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level, - const char *modname, const char *fmt, ...) +void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level, + const char *fmt, ...) { - if (unlikely((comp & rtlpriv->dbg.global_debugcomponents) && - (level <= rtlpriv->dbg.global_debuglevel))) { + if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) && + (level <= rtlpriv->cfg->mod_params->debug_level))) { struct va_format vaf; va_list args; @@ -63,13 +60,25 @@ void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level, vaf.fmt = fmt; vaf.va = &args; - printk(KERN_DEBUG "%s:%ps:<%lx-%x> %pV", - modname, __builtin_return_address(0), - in_interrupt(), in_atomic(), - &vaf); + pr_info("%pV", &vaf); va_end(args); } } -EXPORT_SYMBOL_GPL(_rtl_dbg_trace); +EXPORT_SYMBOL_GPL(_rtl_dbg_print); + +void _rtl_dbg_print_data(struct rtl_priv *rtlpriv, u64 comp, int level, + const char *titlestring, + const void *hexdata, int hexdatalen) +{ + if (unlikely(((comp) & rtlpriv->cfg->mod_params->debug_mask) && + ((level) <= rtlpriv->cfg->mod_params->debug_level))) { + pr_info("In process \"%s\" (pid %i): %s\n", + current->comm, current->pid, titlestring); + print_hex_dump_bytes("", DUMP_PREFIX_NONE, + hexdata, hexdatalen); + } +} +EXPORT_SYMBOL_GPL(_rtl_dbg_print_data); + #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h index a6cc3ca05c5e..bf5339f1c1bc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.h +++ b/drivers/net/wireless/realtek/rtlwifi/debug.h @@ -168,34 +168,29 @@ enum dbgp_flag_e { struct rtl_priv; -__printf(5, 6) +__printf(4, 5) void _rtl_dbg_trace(struct rtl_priv *rtlpriv, int comp, int level, - const char *modname, const char *fmt, ...); + const char *fmt, ...); + +__printf(4, 5) +void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level, + const char *fmt, ...); + +void _rtl_dbg_print_data(struct rtl_priv *rtlpriv, u64 comp, int level, + const char *titlestring, + const void *hexdata, int hexdatalen); #define RT_TRACE(rtlpriv, comp, level, fmt, ...) \ _rtl_dbg_trace(rtlpriv, comp, level, \ - KBUILD_MODNAME, fmt, ##__VA_ARGS__) + fmt, ##__VA_ARGS__) #define RTPRINT(rtlpriv, dbgtype, dbgflag, fmt, ...) \ -do { \ - if (unlikely(rtlpriv->dbg.dbgp_type[dbgtype] & dbgflag)) { \ - printk(KERN_DEBUG KBUILD_MODNAME ": " fmt, \ - ##__VA_ARGS__); \ - } \ -} while (0) + _rtl_dbg_print(rtlpriv, dbgtype, dbgflag, fmt, ##__VA_ARGS__) #define RT_PRINT_DATA(rtlpriv, _comp, _level, _titlestring, _hexdata, \ _hexdatalen) \ -do { \ - if (unlikely(((_comp) & rtlpriv->dbg.global_debugcomponents) && \ - (_level <= rtlpriv->dbg.global_debuglevel))) { \ - printk(KERN_DEBUG "%s: In process \"%s\" (pid %i): %s\n", \ - KBUILD_MODNAME, current->comm, current->pid, \ - _titlestring); \ - print_hex_dump_bytes("", DUMP_PREFIX_NONE, \ - _hexdata, _hexdatalen); \ - } \ -} while (0) + _rtl_dbg_print_data(rtlpriv, _comp, _level, \ + _titlestring, _hexdata, _hexdatalen) #else @@ -223,6 +218,4 @@ static inline void RT_PRINT_DATA(struct rtl_priv *rtlpriv, } #endif - -void rtl_dbgp_flag_init(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index afc7550e8e41..eb58633e674a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -31,6 +31,9 @@ static const u8 MAX_PGPKT_SIZE = 9; static const u8 PGPKT_DATA_SIZE = 8; static const int EFUSE_MAX_SIZE = 512; +#define START_ADDRESS 0x1000 +#define REG_MCUFWDL 0x0080 + static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { {0, 0, 0, 2}, {0, 1, 0, 2}, @@ -1320,3 +1323,45 @@ int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv, return 0; } EXPORT_SYMBOL_GPL(rtl_get_hwinfo); + +void rtl_fw_block_write(struct ieee80211_hw *hw, const u8 *buffer, u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *pu4byteptr = (u8 *)buffer; + u32 i; + + for (i = 0; i < size; i++) + rtl_write_byte(rtlpriv, (START_ADDRESS + i), *(pu4byteptr + i)); +} +EXPORT_SYMBOL_GPL(rtl_fw_block_write); + +void rtl_fw_page_write(struct ieee80211_hw *hw, u32 page, const u8 *buffer, + u32 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value8; + u8 u8page = (u8)(page & 0x07); + + value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; + + rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); + rtl_fw_block_write(hw, buffer, size); +} +EXPORT_SYMBOL_GPL(rtl_fw_page_write); + +void rtl_fill_dummy(u8 *pfwbuf, u32 *pfwlen) +{ + u32 fwlen = *pfwlen; + u8 remain = (u8)(fwlen % 4); + + remain = (remain == 0) ? 0 : (4 - remain); + + while (remain > 0) { + pfwbuf[fwlen] = 0; + fwlen++; + remain--; + } + + *pfwlen = fwlen; +} +EXPORT_SYMBOL_GPL(rtl_fill_dummy); diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h index 51aa1210def5..1338ae63fe54 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.h +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h @@ -111,5 +111,9 @@ void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv, int max_size, u8 *hwinfo, int *params); +void rtl_fill_dummy(u8 *pfwbuf, u32 *pfwlen); +void rtl_fw_page_write(struct ieee80211_hw *hw, u32 page, const u8 *buffer, + u32 size); +void rtl_fw_block_write(struct ieee80211_hw *hw, const u8 *buffer, u32 size); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 81ac0b393304..b402f438b1af 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -2212,16 +2212,6 @@ int rtl_pci_probe(struct pci_dev *pdev, rtlpriv->intf_ops = &rtl_pci_ops; rtlpriv->glb_var = &rtl_global_var; - /* - *init dbgp flags before all - *other functions, because we will - *use it in other funtions like - *RT_TRACE/RT_PRINT/RTL_PRINT_DATA - *you can not use these macro - *before this - */ - rtl_dbgp_flag_init(hw); - /* MEM map */ err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { @@ -2299,12 +2289,6 @@ int rtl_pci_probe(struct pci_dev *pdev, } rtlpriv->mac80211.mac80211_registered = 1; - err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); - if (err) { - pr_err("failed to create sysfs device attributes\n"); - goto fail3; - } - /*init rfkill */ rtl_init_rfkill(hw); /* Init PCI sw */ @@ -2354,8 +2338,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) wait_for_completion(&rtlpriv->firmware_loading_complete); clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); - sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group); - /*ieee80211_unregister_hw will call ops_stop */ if (rtlmac->mac80211_registered == 1) { ieee80211_unregister_hw(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c index afa784a46634..21ed9ad3be7a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c @@ -27,6 +27,7 @@ #include "../pci.h" #include "../base.h" #include "../core.h" +#include "../efuse.h" #include "reg.h" #include "def.h" #include "fw.h" @@ -53,63 +54,6 @@ static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } -static void _rtl88e_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *)buffer; - u32 *pu4BytePtr = (u32 *)buffer; - u32 i, offset, blockcount, remainsize; - - blockcount = size / blocksize; - remainsize = size % blocksize; - - for (i = 0; i < blockcount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), - *(pu4BytePtr + i)); - } - - if (remainsize) { - offset = blockcount * blocksize; - bufferptr += offset; - for (i = 0; i < remainsize; i++) { - rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + - offset + i), *(bufferptr + i)); - } - } -} - -static void _rtl88e_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8) (page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - _rtl88e_fw_block_write(hw, buffer, size); -} - -static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8) (fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - - *pfwlen = fwlen; -} - static void _rtl88e_write_fw(struct ieee80211_hw *hw, enum version_8188e version, u8 *buffer, u32 size) { @@ -120,7 +64,7 @@ static void _rtl88e_write_fw(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); - _rtl88e_fill_dummy(bufferptr, &size); + rtl_fill_dummy(bufferptr, &size); pagenums = size / FW_8192C_PAGE_SIZE; remainsize = size % FW_8192C_PAGE_SIZE; @@ -130,15 +74,14 @@ static void _rtl88e_write_fw(struct ieee80211_hw *hw, for (page = 0; page < pagenums; page++) { offset = page * FW_8192C_PAGE_SIZE; - _rtl88e_fw_page_write(hw, page, (bufferptr + offset), - FW_8192C_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8192C_PAGE_SIZE); } if (remainsize) { offset = pagenums * FW_8192C_PAGE_SIZE; page = pagenums; - _rtl88e_fw_page_write(hw, page, (bufferptr + offset), - remainsize); + rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 276c74539fb3..7661cfa53032 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -131,8 +131,6 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_RXFOVW | 0); rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -276,7 +274,8 @@ static struct rtl_mod_params rtl88ee_mod_params = { .swctrl_lps = false, .fwctrl_lps = false, .msi_support = true, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; static const struct rtl_hal_cfg rtl88ee_hal_cfg = { @@ -392,7 +391,8 @@ MODULE_DESCRIPTION("Realtek 8188E 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8188efw.bin"); module_param_named(swenc, rtl88ee_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl88ee_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl88ee_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl88ee_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444); @@ -404,7 +404,8 @@ MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index 433ab7f33acf..c7a77467b20e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -27,6 +27,7 @@ #include "../pci.h" #include "../base.h" #include "../core.h" +#include "../efuse.h" #include "../rtl8192ce/reg.h" #include "../rtl8192ce/def.h" #include "fw_common.h" @@ -68,63 +69,6 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } -static void _rtl92c_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *)buffer; - u32 *pu4byteptr = (u32 *)buffer; - u32 i, offset, blockcount, remainsize; - - blockcount = size / blocksize; - remainsize = size % blocksize; - - for (i = 0; i < blockcount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), - *(pu4byteptr + i)); - } - - if (remainsize) { - offset = blockcount * blocksize; - bufferptr += offset; - for (i = 0; i < remainsize; i++) { - rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + - offset + i), *(bufferptr + i)); - } - } -} - -static void _rtl92c_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8) (page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - _rtl92c_fw_block_write(hw, buffer, size); -} - -static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8) (fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - - *pfwlen = fwlen; -} - static void _rtl92c_write_fw(struct ieee80211_hw *hw, enum version_8192c version, u8 *buffer, u32 size) { @@ -140,7 +84,7 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw, u32 page, offset; if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) - _rtl92c_fill_dummy(bufferptr, &size); + rtl_fill_dummy(bufferptr, &size); pageNums = size / FW_8192C_PAGE_SIZE; remainsize = size % FW_8192C_PAGE_SIZE; @@ -150,18 +94,18 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw, for (page = 0; page < pageNums; page++) { offset = page * FW_8192C_PAGE_SIZE; - _rtl92c_fw_page_write(hw, page, (bufferptr + offset), - FW_8192C_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8192C_PAGE_SIZE); } if (remainsize) { offset = pageNums * FW_8192C_PAGE_SIZE; page = pageNums; - _rtl92c_fw_page_write(hw, page, (bufferptr + offset), - remainsize); + rtl_fw_page_write(hw, page, (bufferptr + offset), + remainsize); } } else { - _rtl92c_fw_block_write(hw, buffer, size); + rtl_fw_block_write(hw, buffer, size); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index 9bd2bff6212a..efedd918d10a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -130,8 +130,6 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -247,7 +245,8 @@ static struct rtl_mod_params rtl92ce_mod_params = { .inactiveps = true, .swctrl_lps = false, .fwctrl_lps = true, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; static const struct rtl_hal_cfg rtl92ce_hal_cfg = { @@ -364,7 +363,8 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cfwU.bin"); MODULE_FIRMWARE("rtlwifi/rtl8192cfwU_B.bin"); module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92ce_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl92ce_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl92ce_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); @@ -372,7 +372,8 @@ MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index 935e8308e2e6..96c923b3feb4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -61,7 +61,6 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.dm_flag = 0; rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; rtlpriv->cfg->mod_params->sw_crypto = rtlpriv->cfg->mod_params->sw_crypto; @@ -157,13 +156,16 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { static struct rtl_mod_params rtl92cu_mod_params = { .sw_crypto = 0, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; module_param_named(swenc, rtl92cu_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92cu_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl92cu_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl92cu_mod_params.debug_mask, ullong, 0644); MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = { /* rx */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 6da6e2acfbec..1611e42479d9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -477,14 +477,14 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc) */ static void _rtl_tx_desc_checksum(u8 *txdesc) { - u16 *ptr = (u16 *)txdesc; + __le16 *ptr = (__le16 *)txdesc; u16 checksum = 0; u32 index; /* Clear first */ SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0); for (index = 0; index < 16; index++) - checksum = checksum ^ (*(ptr + index)); + checksum = checksum ^ le16_to_cpu(*(ptr + index)); SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index df88e39301c2..487eec89bc29 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -92,129 +92,107 @@ struct rx_drv_info_92c { u8 reserve:4; } __packed; -/* Define a macro that takes a le32 word, converts it to host ordering, - * right shifts by a specified count, creates a mask of the specified - * bit count, and extracts that number of bits. - */ - -#define SHIFT_AND_MASK_LE(__pdesc, __shift, __bits) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__bits)) - -/* Define a macro that clears a bit field in an le32 word and - * sets the specified value into that bit field. The resulting - * value remains in le32 ordering; however, it is properly converted - * to host ordering for the clear and set operations before conversion - * back to le32. - */ - -#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \ - (*(__le32 *)(__pdesc) = \ - (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \ - (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \ - (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); - /* macros to read various fields in RX descriptor */ /* DWORD 0 */ #define GET_RX_DESC_PKT_LEN(__rxdesc) \ - SHIFT_AND_MASK_LE((__rxdesc), 0, 14) + LE_BITS_TO_4BYTE((__rxdesc), 0, 14) #define GET_RX_DESC_CRC32(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 14, 1) + LE_BITS_TO_4BYTE(__rxdesc, 14, 1) #define GET_RX_DESC_ICV(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 15, 1) + LE_BITS_TO_4BYTE(__rxdesc, 15, 1) #define GET_RX_DESC_DRVINFO_SIZE(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 16, 4) + LE_BITS_TO_4BYTE(__rxdesc, 16, 4) #define GET_RX_DESC_SECURITY(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 20, 3) + LE_BITS_TO_4BYTE(__rxdesc, 20, 3) #define GET_RX_DESC_QOS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 23, 1) + LE_BITS_TO_4BYTE(__rxdesc, 23, 1) #define GET_RX_DESC_SHIFT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 24, 2) + LE_BITS_TO_4BYTE(__rxdesc, 24, 2) #define GET_RX_DESC_PHY_STATUS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 26, 1) + LE_BITS_TO_4BYTE(__rxdesc, 26, 1) #define GET_RX_DESC_SWDEC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 27, 1) + LE_BITS_TO_4BYTE(__rxdesc, 27, 1) #define GET_RX_DESC_LAST_SEG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 28, 1) + LE_BITS_TO_4BYTE(__rxdesc, 28, 1) #define GET_RX_DESC_FIRST_SEG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 29, 1) + LE_BITS_TO_4BYTE(__rxdesc, 29, 1) #define GET_RX_DESC_EOR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 30, 1) + LE_BITS_TO_4BYTE(__rxdesc, 30, 1) #define GET_RX_DESC_OWN(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 31, 1) + LE_BITS_TO_4BYTE(__rxdesc, 31, 1) /* DWORD 1 */ #define GET_RX_DESC_MACID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 0, 5) + LE_BITS_TO_4BYTE(__rxdesc + 4, 0, 5) #define GET_RX_DESC_TID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 5, 4) + LE_BITS_TO_4BYTE(__rxdesc + 4, 5, 4) #define GET_RX_DESC_PAGGR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 14, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 14, 1) #define GET_RX_DESC_FAGGR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 15, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 15, 1) #define GET_RX_DESC_A1_FIT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 16, 4) + LE_BITS_TO_4BYTE(__rxdesc + 4, 16, 4) #define GET_RX_DESC_A2_FIT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 20, 4) + LE_BITS_TO_4BYTE(__rxdesc + 4, 20, 4) #define GET_RX_DESC_PAM(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 24, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 24, 1) #define GET_RX_DESC_PWR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 25, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 25, 1) #define GET_RX_DESC_MORE_DATA(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 26, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 26, 1) #define GET_RX_DESC_MORE_FRAG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 27, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 27, 1) #define GET_RX_DESC_TYPE(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 28, 2) + LE_BITS_TO_4BYTE(__rxdesc + 4, 28, 2) #define GET_RX_DESC_MC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 30, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 30, 1) #define GET_RX_DESC_BC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 31, 1) + LE_BITS_TO_4BYTE(__rxdesc + 4, 31, 1) /* DWORD 2 */ #define GET_RX_DESC_SEQ(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 0, 12) + LE_BITS_TO_4BYTE(__rxdesc + 8, 0, 12) #define GET_RX_DESC_FRAG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 12, 4) + LE_BITS_TO_4BYTE(__rxdesc + 8, 12, 4) #define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 16, 8) + LE_BITS_TO_4BYTE(__rxdesc + 8, 16, 8) #define GET_RX_DESC_NEXT_IND(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 30, 1) + LE_BITS_TO_4BYTE(__rxdesc + 8, 30, 1) /* DWORD 3 */ #define GET_RX_DESC_RX_MCS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 0, 6) + LE_BITS_TO_4BYTE(__rxdesc + 12, 0, 6) #define GET_RX_DESC_RX_HT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 6, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 6, 1) #define GET_RX_DESC_AMSDU(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 7, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 7, 1) #define GET_RX_DESC_SPLCP(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 8, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 8, 1) #define GET_RX_DESC_BW(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 9, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 9, 1) #define GET_RX_DESC_HTC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 10, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 10, 1) #define GET_RX_DESC_TCP_CHK_RPT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 11, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 11, 1) #define GET_RX_DESC_IP_CHK_RPT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 12, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 12, 1) #define GET_RX_DESC_TCP_CHK_VALID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 13, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 13, 1) #define GET_RX_DESC_HWPC_ERR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 14, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 14, 1) #define GET_RX_DESC_HWPC_IND(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 15, 1) + LE_BITS_TO_4BYTE(__rxdesc + 12, 15, 1) #define GET_RX_DESC_IV0(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 16, 16) + LE_BITS_TO_4BYTE(__rxdesc + 12, 16, 16) /* DWORD 4 */ #define GET_RX_DESC_IV1(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+16, 0, 32) + LE_BITS_TO_4BYTE(__rxdesc + 16, 0, 32) /* DWORD 5 */ #define GET_RX_DESC_TSFL(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+20, 0, 32) + LE_BITS_TO_4BYTE(__rxdesc + 20, 0, 32) /*======================= tx desc ============================================*/ @@ -222,182 +200,182 @@ struct rx_drv_info_92c { /* Dword 0 */ #define SET_TX_DESC_PKT_SIZE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 0, 16, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 0, 16, __value) #define SET_TX_DESC_OFFSET(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 16, 8, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 16, 8, __value) #define SET_TX_DESC_BMC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 24, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 24, 1, __value) #define SET_TX_DESC_HTC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 25, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 25, 1, __value) #define SET_TX_DESC_LAST_SEG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 26, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 26, 1, __value) #define SET_TX_DESC_FIRST_SEG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 27, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 27, 1, __value) #define SET_TX_DESC_LINIP(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 28, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 28, 1, __value) #define SET_TX_DESC_NO_ACM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 29, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 29, 1, __value) #define SET_TX_DESC_GF(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 30, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 30, 1, __value) #define SET_TX_DESC_OWN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 31, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value) /* Dword 1 */ #define SET_TX_DESC_MACID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 0, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value) #define SET_TX_DESC_AGG_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 5, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 5, 1, __value) #define SET_TX_DESC_AGG_BREAK(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 6, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 6, 1, __value) #define SET_TX_DESC_RDG_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 7, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 7, 1, __value) #define SET_TX_DESC_QUEUE_SEL(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 8, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 8, 5, __value) #define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 13, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 13, 1, __value) #define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 14, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 14, 1, __value) #define SET_TX_DESC_PIFS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 15, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 15, 1, __value) #define SET_TX_DESC_RATE_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 16, 4, __value) #define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 16, 4, __value) #define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 20, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 20, 1, __value) #define SET_TX_DESC_EN_DESC_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 21, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 21, 1, __value) #define SET_TX_DESC_SEC_TYPE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 22, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 22, 2, __value) #define SET_TX_DESC_PKT_OFFSET(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 26, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 4, 26, 5, __value) /* Dword 2 */ #define SET_TX_DESC_RTS_RC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 0, 6, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 0, 6, __value) #define SET_TX_DESC_DATA_RC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 6, 6, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 6, 6, __value) #define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 14, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 14, 2, __value) #define SET_TX_DESC_MORE_FRAG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 17, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 17, 1, __value) #define SET_TX_DESC_RAW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 18, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 18, 1, __value) #define SET_TX_DESC_CCX(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 19, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 19, 1, __value) #define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 20, 3, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 20, 3, __value) #define SET_TX_DESC_ANTSEL_A(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 24, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 24, 1, __value) #define SET_TX_DESC_ANTSEL_B(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 25, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 25, 1, __value) #define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 26, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 26, 2, __value) #define SET_TX_DESC_TX_ANTL(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 28, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 28, 2, __value) #define SET_TX_DESC_TX_ANT_HT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 30, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 8, 30, 2, __value) /* Dword 3 */ #define SET_TX_DESC_NEXT_HEAP_PAGE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 0, 8, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 12, 0, 8, __value) #define SET_TX_DESC_TAIL_PAGE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 8, 8, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 12, 8, 8, __value) #define SET_TX_DESC_SEQ(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 16, 12, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 12, 16, 12, __value) #define SET_TX_DESC_PKT_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 28, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 12, 28, 4, __value) /* Dword 4 */ #define SET_TX_DESC_RTS_RATE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 0, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 0, 5, __value) #define SET_TX_DESC_AP_DCFE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 5, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 5, 1, __value) #define SET_TX_DESC_QOS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 6, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 6, 1, __value) #define SET_TX_DESC_HWSEQ_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 7, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 7, 1, __value) #define SET_TX_DESC_USE_RATE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 8, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 8, 1, __value) #define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 9, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 9, 1, __value) #define SET_TX_DESC_DISABLE_FB(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 10, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 10, 1, __value) #define SET_TX_DESC_CTS2SELF(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 11, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 11, 1, __value) #define SET_TX_DESC_RTS_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 12, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 12, 1, __value) #define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 13, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 13, 1, __value) #define SET_TX_DESC_WAIT_DCTS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 18, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 18, 1, __value) #define SET_TX_DESC_CTS2AP_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 19, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 19, 1, __value) #define SET_TX_DESC_DATA_SC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 20, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 20, 2, __value) #define SET_TX_DESC_DATA_STBC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 22, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 22, 2, __value) #define SET_TX_DESC_DATA_SHORT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 24, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 24, 1, __value) #define SET_TX_DESC_DATA_BW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 25, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 25, 1, __value) #define SET_TX_DESC_RTS_SHORT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 26, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 26, 1, __value) #define SET_TX_DESC_RTS_BW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 27, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 27, 1, __value) #define SET_TX_DESC_RTS_SC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 28, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 28, 2, __value) #define SET_TX_DESC_RTS_STBC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 30, 2, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 16, 30, 2, __value) /* Dword 5 */ #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) + SET_BITS_TO_LE_4BYTE(__pdesc + 20, 0, 6, __val) #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) + SET_BITS_TO_LE_4BYTE(__pdesc + 20, 6, 1, __val) #define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) + SET_BITS_TO_LE_4BYTE(__pdesc + 20, 7, 1, __val) #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 8, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 20, 8, 5, __value) #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 13, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 20, 13, 4, __value) #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 17, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 20, 17, 1, __value) #define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 18, 6, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 20, 18, 6, __value) #define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 24, 8, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 20, 24, 8, __value) /* Dword 6 */ #define SET_TX_DESC_TXAGC_A(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 0, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 0, 5, __value) #define SET_TX_DESC_TXAGC_B(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 5, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 5, 5, __value) #define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 10, 1, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 10, 1, __value) #define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 11, 5, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 11, 5, __value) #define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 16, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 16, 4, __value) #define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 20, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 20, 4, __value) #define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 24, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 24, 4, __value) #define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 28, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 24, 28, 4, __value) /* Dword 7 */ #define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 0, 16, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 28, 0, 16, __value) #define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 16, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 28, 16, 4, __value) #define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 20, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 28, 20, 4, __value) #define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 24, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 28, 24, 4, __value) #define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 28, 4, __value) + SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value) int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index aa1e51c871df..88faeab2574f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -26,6 +26,7 @@ #include "../wifi.h" #include "../pci.h" #include "../base.h" +#include "../efuse.h" #include "reg.h" #include "def.h" #include "fw.h" @@ -59,84 +60,31 @@ static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } -static void _rtl92d_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *) buffer; - u32 *pu4BytePtr = (u32 *) buffer; - u32 i, offset, blockCount, remainSize; - - blockCount = size / blocksize; - remainSize = size % blocksize; - for (i = 0; i < blockCount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset), - *(pu4BytePtr + i)); - } - if (remainSize) { - offset = blockCount * blocksize; - bufferptr += offset; - for (i = 0; i < remainSize; i++) { - rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS + - offset + i), *(bufferptr + i)); - } - } -} - -static void _rtl92d_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8) (page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - _rtl92d_fw_block_write(hw, buffer, size); -} - -static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8) (fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - *pfwlen = fwlen; -} - static void _rtl92d_write_fw(struct ieee80211_hw *hw, enum version_8192d version, u8 *buffer, u32 size) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 *bufferPtr = buffer; - u32 pagenums, remainSize; + u8 *bufferptr = buffer; + u32 pagenums, remainsize; u32 page, offset; RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) - _rtl92d_fill_dummy(bufferPtr, &size); + rtl_fill_dummy(bufferptr, &size); pagenums = size / FW_8192D_PAGE_SIZE; - remainSize = size % FW_8192D_PAGE_SIZE; + remainsize = size % FW_8192D_PAGE_SIZE; if (pagenums > 8) pr_err("Page numbers should not greater then 8\n"); for (page = 0; page < pagenums; page++) { offset = page * FW_8192D_PAGE_SIZE; - _rtl92d_fw_page_write(hw, page, (bufferPtr + offset), - FW_8192D_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8192D_PAGE_SIZE); } - if (remainSize) { + if (remainsize) { offset = pagenums * FW_8192D_PAGE_SIZE; page = pagenums; - _rtl92d_fw_page_write(hw, page, (bufferPtr + offset), - remainSize); + rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); } } @@ -323,7 +271,6 @@ int rtl92d_download_fw(struct ieee80211_hw *hw) spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); if (err) pr_err("fw is not ready to run!\n"); - goto exit; exit: err = _rtl92d_fw_init(hw); return err; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index 51463d7b130a..16132c66e5e1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -140,8 +140,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -254,7 +252,8 @@ static struct rtl_mod_params rtl92de_mod_params = { .inactiveps = true, .swctrl_lps = true, .fwctrl_lps = false, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; static const struct rtl_hal_cfg rtl92de_hal_cfg = { @@ -364,15 +363,17 @@ MODULE_DESCRIPTION("Realtek 8192DE 802.11n Dual Mac PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192defw.bin"); module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92de_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl92de_mod_params.debug_level, int, 0644); module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444); +module_param_named(debug_mask, rtl92de_mod_params.debug_mask, ullong, 0644); MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 78ee6e1d1850..9d7a16c9e74e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -27,6 +27,7 @@ #include "../pci.h" #include "../base.h" #include "../core.h" +#include "../efuse.h" #include "reg.h" #include "def.h" #include "fw.h" @@ -48,64 +49,6 @@ static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } -static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *)buffer; - u32 *pu4byteptr = (u32 *)buffer; - u32 i, offset, blockcount, remainsize; - - blockcount = size / blocksize; - remainsize = size % blocksize; - - for (i = 0; i < blockcount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), - *(pu4byteptr + i)); - } - - if (remainsize) { - offset = blockcount * blocksize; - bufferptr += offset; - for (i = 0; i < remainsize; i++) { - rtl_write_byte(rtlpriv, - (FW_8192C_START_ADDRESS + offset + i), - *(bufferptr + i)); - } - } -} - -static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8)(page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - - _rtl92ee_fw_block_write(hw, buffer, size); -} - -static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8)(fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - - *pfwlen = fwlen; -} - static void _rtl92ee_write_fw(struct ieee80211_hw *hw, enum version_8192e version, u8 *buffer, u32 size) @@ -117,7 +60,7 @@ static void _rtl92ee_write_fw(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size); - _rtl92ee_fill_dummy(bufferptr, &size); + rtl_fill_dummy(bufferptr, &size); pagenums = size / FW_8192C_PAGE_SIZE; remainsize = size % FW_8192C_PAGE_SIZE; @@ -127,16 +70,15 @@ static void _rtl92ee_write_fw(struct ieee80211_hw *hw, for (page = 0; page < pagenums; page++) { offset = page * FW_8192C_PAGE_SIZE; - _rtl92ee_fw_page_write(hw, page, (bufferptr + offset), - FW_8192C_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8192C_PAGE_SIZE); udelay(2); } if (remainsize) { offset = pagenums * FW_8192C_PAGE_SIZE; page = pagenums; - _rtl92ee_fw_page_write(hw, page, (bufferptr + offset), - remainsize); + rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index eddc704b3ee3..554f2dc86bc5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -133,8 +133,6 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) 0); rtlpci->irq_mask[1] = (u32)(IMR_RXFOVW | 0); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -258,7 +256,8 @@ static struct rtl_mod_params rtl92ee_mod_params = { .swctrl_lps = false, .fwctrl_lps = true, .msi_support = true, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; static const struct rtl_hal_cfg rtl92ee_hal_cfg = { @@ -368,7 +367,8 @@ MODULE_DESCRIPTION("Realtek 8192EE 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192eefw.bin"); module_param_named(swenc, rtl92ee_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92ee_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl92ee_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl92ee_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl92ee_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl92ee_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl92ee_mod_params.fwctrl_lps, bool, 0444); @@ -380,7 +380,8 @@ MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index 3c66d00abbac..2006b09ea74f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -178,8 +178,6 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) rtlpci->first_init = true; - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -297,7 +295,8 @@ static struct rtl_mod_params rtl92se_mod_params = { .inactiveps = true, .swctrl_lps = true, .fwctrl_lps = false, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, }; /* Because memory R/W bursting will cause system hang/crash @@ -416,7 +415,8 @@ MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92se_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl92se_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl92se_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); @@ -424,7 +424,8 @@ MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 401f54266f15..7bf9f2557920 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -145,8 +145,6 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) (u32)(PHIMR_RXFOVW | 0); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -268,7 +266,8 @@ static struct rtl_mod_params rtl8723e_mod_params = { .inactiveps = true, .swctrl_lps = false, .fwctrl_lps = true, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, .msi_support = false, .disable_watchdog = false, }; @@ -382,7 +381,8 @@ MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8723efw.bin"); module_param_named(swenc, rtl8723e_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl8723e_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl8723e_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl8723e_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl8723e_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl8723e_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl8723e_mod_params.fwctrl_lps, bool, 0444); @@ -394,7 +394,8 @@ MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index dd42c1a6d986..e571b876f0af 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -144,8 +144,6 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) HSIMR_RON_INT_EN | 0); - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -271,7 +269,8 @@ static struct rtl_mod_params rtl8723be_mod_params = { .fwctrl_lps = true, .msi_support = false, .disable_watchdog = false, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, .ant_sel = 0, }; @@ -386,7 +385,8 @@ MODULE_DESCRIPTION("Realtek 8723BE 802.11n PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8723befw.bin"); module_param_named(swenc, rtl8723be_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl8723be_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl8723be_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl8723be_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444); @@ -399,7 +399,8 @@ MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); MODULE_PARM_DESC(ant_sel, "Set to 1 or 2 to force antenna number (default 0)\n"); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c index 8e0d038df701..ac573d69f6d6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c @@ -26,6 +26,7 @@ #include "../wifi.h" #include "../pci.h" #include "../base.h" +#include "../efuse.h" #include "fw_common.h" #include <linux/module.h> @@ -53,65 +54,6 @@ void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable) } EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download); -void rtl8723_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *)buffer; - u32 *pu4byteptr = (u32 *)buffer; - u32 i, offset, blockcount, remainsize; - - blockcount = size / blocksize; - remainsize = size % blocksize; - - for (i = 0; i < blockcount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), - *(pu4byteptr + i)); - } - if (remainsize) { - offset = blockcount * blocksize; - bufferptr += offset; - for (i = 0; i < remainsize; i++) { - rtl_write_byte(rtlpriv, - (FW_8192C_START_ADDRESS + offset + i), - *(bufferptr + i)); - } - } -} -EXPORT_SYMBOL_GPL(rtl8723_fw_block_write); - -void rtl8723_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8) (page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - rtl8723_fw_block_write(hw, buffer, size); -} -EXPORT_SYMBOL_GPL(rtl8723_fw_page_write); - -void rtl8723_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8) (fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - *pfwlen = fwlen; -} -EXPORT_SYMBOL(rtl8723_fill_dummy); - void rtl8723_write_fw(struct ieee80211_hw *hw, enum version_8723e version, u8 *buffer, u32 size, u8 max_page) @@ -123,7 +65,7 @@ void rtl8723_write_fw(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); - rtl8723_fill_dummy(bufferptr, &size); + rtl_fill_dummy(bufferptr, &size); page_nums = size / FW_8192C_PAGE_SIZE; remain_size = size % FW_8192C_PAGE_SIZE; @@ -134,15 +76,14 @@ void rtl8723_write_fw(struct ieee80211_hw *hw, } for (page = 0; page < page_nums; page++) { offset = page * FW_8192C_PAGE_SIZE; - rtl8723_fw_page_write(hw, page, (bufferptr + offset), - FW_8192C_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8192C_PAGE_SIZE); } if (remain_size) { offset = page_nums * FW_8192C_PAGE_SIZE; page = page_nums; - rtl8723_fw_page_write(hw, page, (bufferptr + offset), - remain_size); + rtl_fw_page_write(hw, page, (bufferptr + offset), remain_size); } RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n"); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h index 8ea372d1626e..77c25a976233 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h @@ -28,7 +28,6 @@ #define REG_SYS_FUNC_EN 0x0002 #define REG_MCUFWDL 0x0080 -#define FW_8192C_START_ADDRESS 0x1000 #define FW_8192C_PAGE_SIZE 4096 #define FW_8723A_POLLING_TIMEOUT_COUNT 1000 #define FW_8723B_POLLING_TIMEOUT_COUNT 6000 @@ -84,10 +83,6 @@ enum rtl8723be_cmd { void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw); void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw); void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable); -void rtl8723_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size); -void rtl8723_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size); void rtl8723_write_fw(struct ieee80211_hw *hw, enum version_8723e version, u8 *buffer, u32 size, u8 max_page); @@ -95,6 +90,5 @@ int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, int count); int rtl8723_download_fw(struct ieee80211_hw *hw, bool is_8723be, int count); bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); -void rtl8723_fill_dummy(u8 *pfwbuf, u32 *pfwlen); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index 94e97dce5457..328c64d465ba 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -27,6 +27,7 @@ #include "../pci.h" #include "../base.h" #include "../core.h" +#include "../efuse.h" #include "reg.h" #include "def.h" #include "fw.h" @@ -51,63 +52,6 @@ static void _rtl8821ae_enable_fw_download(struct ieee80211_hw *hw, bool enable) } } -static void _rtl8821ae_fw_block_write(struct ieee80211_hw *hw, - const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 blocksize = sizeof(u32); - u8 *bufferptr = (u8 *)buffer; - u32 *pu4byteptr = (u32 *)buffer; - u32 i, offset, blockcount, remainsize; - - blockcount = size / blocksize; - remainsize = size % blocksize; - - for (i = 0; i < blockcount; i++) { - offset = i * blocksize; - rtl_write_dword(rtlpriv, (FW_8821AE_START_ADDRESS + offset), - *(pu4byteptr + i)); - } - - if (remainsize) { - offset = blockcount * blocksize; - bufferptr += offset; - for (i = 0; i < remainsize; i++) { - rtl_write_byte(rtlpriv, (FW_8821AE_START_ADDRESS + - offset + i), *(bufferptr + i)); - } - } -} - -static void _rtl8821ae_fw_page_write(struct ieee80211_hw *hw, - u32 page, const u8 *buffer, u32 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value8; - u8 u8page = (u8)(page & 0x07); - - value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; - - rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); - _rtl8821ae_fw_block_write(hw, buffer, size); -} - -static void _rtl8821ae_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 fwlen = *pfwlen; - u8 remain = (u8)(fwlen % 4); - - remain = (remain == 0) ? 0 : (4 - remain); - - while (remain > 0) { - pfwbuf[fwlen] = 0; - fwlen++; - remain--; - } - - *pfwlen = fwlen; -} - static void _rtl8821ae_write_fw(struct ieee80211_hw *hw, enum version_8821ae version, u8 *buffer, u32 size) @@ -119,7 +63,7 @@ static void _rtl8821ae_write_fw(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); - _rtl8821ae_fill_dummy(bufferptr, &size); + rtl_fill_dummy(bufferptr, &size); pagenums = size / FW_8821AE_PAGE_SIZE; remainsize = size % FW_8821AE_PAGE_SIZE; @@ -129,15 +73,14 @@ static void _rtl8821ae_write_fw(struct ieee80211_hw *hw, for (page = 0; page < pagenums; page++) { offset = page * FW_8821AE_PAGE_SIZE; - _rtl8821ae_fw_page_write(hw, page, (bufferptr + offset), - FW_8821AE_PAGE_SIZE); + rtl_fw_page_write(hw, page, (bufferptr + offset), + FW_8821AE_PAGE_SIZE); } if (remainsize) { offset = pagenums * FW_8821AE_PAGE_SIZE; page = pagenums; - _rtl8821ae_fw_page_write(hw, page, (bufferptr + offset), - remainsize); + rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index 220de5f89dbc..cd2a53b7e053 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -160,8 +160,6 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.wo_wlan_mode = WAKE_ON_MAGIC_PACKET | WAKE_ON_PATTERN_MATCH; - /* for debug level */ - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; /* for LPS & IPS */ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; @@ -309,7 +307,8 @@ static struct rtl_mod_params rtl8821ae_mod_params = { .fwctrl_lps = true, .msi_support = true, .int_clear = true, - .debug = 0, + .debug_level = 0, + .debug_mask = 0, .disable_watchdog = 0, }; @@ -430,7 +429,8 @@ MODULE_DESCRIPTION("Realtek 8821ae 802.11ac PCI wireless"); MODULE_FIRMWARE("rtlwifi/rtl8821aefw.bin"); module_param_named(swenc, rtl8821ae_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl8821ae_mod_params.debug, int, 0444); +module_param_named(debug_level, rtl8821ae_mod_params.debug_level, int, 0644); +module_param_named(debug_mask, rtl8821ae_mod_params.debug_mask, ullong, 0644); module_param_named(ips, rtl8821ae_mod_params.inactiveps, bool, 0444); module_param_named(swlps, rtl8821ae_mod_params.swctrl_lps, bool, 0444); module_param_named(fwlps, rtl8821ae_mod_params.fwctrl_lps, bool, 0444); @@ -443,7 +443,8 @@ MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); +MODULE_PARM_DESC(debug_mask, "Set debug mask (default 0)"); MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); MODULE_PARM_DESC(int_clear, "Set to 0 to disable interrupt clear before set (default 1)\n"); diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 916a230aeeaa..4d989b8ab185 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -818,12 +818,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct urb *urb; /* should after adapter start and interrupt enable. */ set_hal_stop(rtlhal); cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); /* Enable software */ SET_USB_STOP(rtlusb); + + /* free pre-allocated URBs from rtl_usb_start() */ + usb_kill_anchored_urbs(&rtlusb->rx_submitted); + + tasklet_kill(&rtlusb->rx_work_tasklet); + cancel_work_sync(&rtlpriv->works.lps_change_work); + + flush_workqueue(rtlpriv->works.rtl_wq); + + skb_queue_purge(&rtlusb->rx_queue); + + while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + usb_free_urb(urb); + } + rtlpriv->cfg->ops->hw_disable(hw); } @@ -1074,7 +1092,6 @@ int rtl_usb_probe(struct usb_interface *intf, rtlpriv->rtlhal.interface = INTF_USB; rtlpriv->cfg = rtl_hal_cfg; rtlpriv->intf_ops = &rtl_usb_ops; - rtl_dbgp_flag_init(hw); /* Init IO handler */ _rtl_usb_io_handler_init(&udev->dev, hw); rtlpriv->cfg->ops->read_chip_version(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index dafe486f8448..310fa90200b2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2221,11 +2221,13 @@ struct rtl_intf_ops { }; struct rtl_mod_params { + /* default: 0,0 */ + u64 debug_mask; /* default: 0 = using hardware encryption */ bool sw_crypto; /* default: 0 = DBG_EMERG (0)*/ - int debug; + int debug_level; /* default: 1 = using no linked power save */ bool inactiveps; @@ -2345,16 +2347,6 @@ struct rtl_works { struct work_struct fill_h2c_cmd; }; -struct rtl_debug { - u32 dbgp_type[DBGP_TYPE_MAX]; - int global_debuglevel; - u64 global_debugcomponents; - - /* add for proc debug */ - struct proc_dir_entry *proc_dir; - char proc_name[20]; -}; - #define MIMO_PS_STATIC 0 #define MIMO_PS_DYNAMIC 1 #define MIMO_PS_NOLIMIT 3 @@ -2583,7 +2575,6 @@ struct rtl_priv { /* sta entry list for ap adhoc or mesh */ struct list_head entry_list; - struct rtl_debug dbg; int max_fw_size; /* @@ -2713,23 +2704,14 @@ enum bt_radio_shared { (le32_to_cpu(_val)) /* Read data from memory */ -#define READEF1BYTE(_ptr) \ +#define READEF1BYTE(_ptr) \ EF1BYTE(*((u8 *)(_ptr))) /* Read le16 data from memory and convert to host ordering */ -#define READEF2BYTE(_ptr) \ +#define READEF2BYTE(_ptr) \ EF2BYTE(*(_ptr)) -#define READEF4BYTE(_ptr) \ +#define READEF4BYTE(_ptr) \ EF4BYTE(*(_ptr)) -/* Write data to memory */ -#define WRITEEF1BYTE(_ptr, _val) \ - (*((u8 *)(_ptr))) = EF1BYTE(_val) -/* Write le16 data to memory in host ordering */ -#define WRITEEF2BYTE(_ptr, _val) \ - (*((u16 *)(_ptr))) = EF2BYTE(_val) -#define WRITEEF4BYTE(_ptr, _val) \ - (*((u32 *)(_ptr))) = EF2BYTE(_val) - /* Create a bit mask * Examples: * BIT_LEN_MASK_32(0) => 0x00000000 @@ -2810,14 +2792,14 @@ value to host byte ordering.*/ * Set subfield of little-endian 4-byte value to specified value. */ #define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u32 *)(__pstart)) = \ - ( \ + *((__le32 *)(__pstart)) = \ + cpu_to_le32( \ LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ ); #define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u16 *)(__pstart)) = \ - ( \ + *((__le16 *)(__pstart)) = \ + cpu_to_le16( \ LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ ); diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 47fe7f96a242..287023ef4a78 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -81,13 +81,6 @@ static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr, sdio_claim_host(func); - if (unlikely(dump)) { - printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr); - print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ", - DUMP_PREFIX_OFFSET, 16, 1, - buf, len, false); - } - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", @@ -107,6 +100,13 @@ static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr, if (WARN_ON(ret)) dev_err(child->parent, "sdio read failed (%d)\n", ret); + if (unlikely(dump)) { + printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr); + print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ", + DUMP_PREFIX_OFFSET, 16, 1, + buf, len, false); + } + return ret; } |